Get multiple random array elements in ruby
You can pass an integer argument to .sample to get multiple random elements from an array in ruby
["this", "is", "a", "til", "post"].sample(2)
# => ["this", "post"]
You can pass an integer argument to .sample to get multiple random elements from an array in ruby
["this", "is", "a", "til", "post"].sample(2)
# => ["this", "post"]
Today I learned you can lint your Factories with FactoryBot.lint. This will run through all your factories, and list any that failed to create. You can also include traits in the listing with FactoryBot.lint traits: true. Useful for ensuring your factories remain valid.
If you're troubleshooting some slow SQL queries, chances are you've used EXPLAIN or even EXPLAIN ANALYZE. But TIL, that you can actually run these in the Rails console on your Rails models (Active Model Relations). It looks something like this -
> User.active.explain
Or if you're on a more recent version of Rails, you can also pass arguments to .explain, such as :analyze -
> User.active.explain(:analyze)
You can also call it on other methods like pluck, etc. -
> User.active.explain.pluck
Be warned that calling .explain will execute the query.
https://devdocs.io/rails~7.2/activerecord/relation#method-i-explain
https://guides.rubyonrails.org/active_record_querying.html#running-explain
When generating a rails column, you can specify an attribute to have a unique constraint like this:
rails g model Song title:string:uniq
In your migration, this will look like:
add_index :songs, :title, unique: true
Today I discovered TOON (Token-Oriented Object Notation), a serialization format designed specifically for LLMs that achieves 30-60% token reduction compared to JSON.
Unlike JSON, TOON eliminates redundant syntax (braces, brackets, most quotes). Unlike CSV, it supports nested fields. It also provides better accuracy through explicit lengths and fields before hand, this seems to make LLM better to understand the data that's comming.
JSON:
{
"users": [
{ "id": 1, "name": "Alice", "role": "admin" },
{ "id": 2, "name": "Bob", "role": "user" }
]
}
TOON:
users[2]{id,name,role}:
1,Alice,admin
2,Bob,user
Keys are declared once, then data flows as comma-separated rows with YAML-style indentation for nesting.
Sometimes I just want to run model rspec tests, or run everything except for those slow feature tests in my rails app. Today I learned you can do that with the --tag option.
To only run model specs:
$ bundle exec rspec --tag type:model
To exclude feature specs (using the ~):
$ bundle exec rspec --tag ~type:feature
What's convenient is rspec-rails will infer the type of the spec based on it's location in the spec/ directory, so even if you don't explicitly tag your tests with type: :model these filters will still work.
Today I learned some cool ways to delete lines of text in (n)vim. Josh TIL'ed that you can execute an Ex command on a buffer with the :g command. So if you want to delete any lines that match pattern, you can run
:g/pattern/d
Which is pretty neat! But you can also flip it - to delete any lines that don't match the pattern, you can use :v or :g!
:v/pattern/d
:g!/pattern/d
You can also restrict to a range of lines - if you want to only delete lines matching pattern between lines 40 and 50, you can do so with:
:40,50 g/pattern/d
Today I learned about React 19.2’s new <Activity> component.
<Activity mode={isShowingSidebar ? "visible" : "hidden"}>
<Sidebar />
</Activity>
When mode="hidden", React unmounts all useEffect, it keeps state cached and yet the DOM stays rendered via display: none.
Switching back to mode="visible" restores the view instantly with its previous state and fire all useEffect again.
This is perfect for tabs, modals, and any UI you want ready-to-go.
reference: React Activity docs
You can see the current execution stack with the caller method in ruby. It will show you where the currently executing method is called.
def my_method
call_me
end
def call_me
puts caller
end
my_method
#=>
#_:2:in `foo'
#_:7:in `<main>'
Today I learned you can modify a json payload in a rails controller to include associated models and filter attributes in the payload with the include and only options.
Say I have a controller that returns all blog Post records as json:
def index
respond_to do |format|
format.json do
render json: Post.all
end
end
end
Now, say I want to include attributes for an associated Author model, but only their first and last name and exclude all other attributes. I can include the authors, and only include first and last name:
def index
respond_to do |format|
format.json do
render json: Post.all, include: {author: {only: [:last_name, :first_name]}}
end
end
end
You can execute ruby code inline with the -e flag on the ruby command
ruby -e 'puts "hello world"'
While .gitignore is great for team-wide ignore patterns, sometimes you need to ignore files just for your local setup without affecting other developers. Instead of modifying the shared .gitignore or creating a global ignore file, you can use .git/info/exclude.
This file works exactly like .gitignore but is private to your local repository and won't be committed or pushed to remote.
Example:
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
Makefile
This keeps your ignores clean and avoids polluting the shared .gitignore with personal preferences.
Today I learned how to list postgres databases from the command line. I use createdb and dropdb all the time to create and drop databases respectively, but alas listdb is not a valid command.
Instead, you can list the databases with psql -l.
$ psql -l
Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
-----------------------------+----------+----------+-------------+-------------+------------+-----------------+-----------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | en-US | icu |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | en-US | icu | =c/postgres +
| | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | en-US | icu | =c/postgres +
| | | | | | | postgres=CTc/postgres
...
React 19.2 added a new hook useEffectEvent that lets us to extract event handlers from effects, so they use the latest props/state without triggering effect re-runs.
Problem: You want an effect to depend on roomId but not theme:
function ChatRoom({ roomId, theme }) {
useEffect(() => {
const connection = createConnection(roomId).then(() => {
showNotification('Connected!', theme);
});
return connection.disconnect;
}, [roomId, theme]);
}
Solution with useEffectEvent:
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});
useEffect(() => {
const connection = createConnection(roomId).then(() => {
onConnected();
});
return connection.disconnect;
}, [roomId]);
}
This way if the theme changes nothing happens, but if the roomId changed then a notification is fired with the latest theme value.
Today I discovered Anubis MCP, an excellent Elixir SDK for building Model Context Protocol (MCP) servers and clients.
Check out the documentation for more examples.
Today I learned that you can configure MCP servers in Claude Code with http headers for authentication/authorization using the CLI:
claude mcp add \
--scope user \
--transport http \
--header "Authorization: Bearer your-token" \
my-mcp http://example.com/mcp;
In this case I decided to use the scope user because I want that MCP being configured for all my projects.
Today I learned about shellcheck, a static analysis tool for shell scripts. I'll be the first to admit that my bash scripts contain a multitude of sins, so a too like this is invaluable to help clean them up.
It can be installed through Homebrew (brew install shellcheck), but also has a web editor available at https://www.shellcheck.net/ if you don't want to install it.
$ shellcheck my_script
You can use Enumerable#tally to get a hash of element counts
["apple", "banana", "apple", "orange", "banana"].tally
=> {"apple"=>2, "banana"=>2, "orange"=>1}
We can even make it work for nested arrays
outfits = [
["Red Shirt"],
["Red Shirt", "Blue Pants"],
["Blue Pants"],
["Red Shirt"],
]
outfits.tally.map { |k, v| [*k, v] }
=>
[
["Red Shirt", 2],
["Red Shirt", "Blue Pants", 1],
["Blue Pants", 1]
]
If you're in a fresh install of linux and stuck on the command line but need to connect to wifi, you can use the iNet Wireless Daemon (iwd) by interacting with it via it's client iwctl. Once you start up the iwctl command prompt, you can scan and connect to a wireless network.
$ iwctl
[iwd]# device list # find the name of your device, likely wlan0 for wifi
[iwd]# station wlan0 scan # scan for networks
[iwd]# station wlan0 get-networks # list available networks from the scan
[iwd]# station wlan0 connect [SSID] # connect to your network
React Native includes a hook for getting the current device's window dimensions in pixels.
const {height, width} = useWindowDimensions();
Sometimes you need to know which shell you're running. It's not a great mystery most of the time, but sometimes you ssh into a new server or spin up a new distro and it's anybody's guess.
You can check $0, which is the path of the currently running program, i.e. your shell.
$ echo $0
-bash
Today I learned about the \%l atom, which can be used to search on the current line, or a specific line, and also above or below the current or specific line. That's kind of a lot in one sentence, so lets break it down:
Say you want to search for a search_term on line 23 of your buffer, you can do this by
/\%23lsearch_term
If you want to search for search_term only on the current line, you can use . instead of a line number
/\%.lsearch_term
You can use the <and > modifiers to match above (<) or below (>) the current line
/\%<.lsearch_term
/\%>.lsearch_term
But you can also replace . with a line number to match above or below that line:
/\%<23lsearch_term
/\%>23lsearch_term
\%V is a useful atom (TIL it's called an atom - and there are a lot of them, see :h pattern-atoms) that can be used to match inside a Visual selection.
Say you have a large file open and want to search for something only within a single area of text, like a method. You can visually select that block of text, enter command mode with :, and prefix the search with \%V to scope the search so that you only get matches inside the selection:
:'<,'>/\%Vsearch_text
You can also use \%V to search and replace.
If you want to switch which android device you are emulating on Android Studio,
More Actions Virtual Device Manager + icon to add a new device, and select the android model you'd like to emulate
Let's say I have a Post model, and send a PATCH XHR request for an instance of Post, handled by the PostsController. Normally, if I want to redirect to the posts_path at the end of the controller action I end the method like so:
def patch
# patch-y things done here
redirect_to posts_path
end # => redirects to PATCH /posts ❌
It's possible, depending on your browser, that instead of redirecting as a GET request to posts_path like you would expect, the original PATCH method is forwarded instead. Most times, this probably isn't what you want. To force the redirect to use the appropriate method for the path you're redirecting to, you can use the 303 See Other status code:
def patch
# patch-y things done here
redirect_to posts_path, status: :see_other
end # => redirects to GET /posts ✅
It's specifically called out in the docs (ActionController::Redirecting) so it seems to be fairly well-known/widespread, but it was a new to me occurrence.
I wanted to view a commit on a different branch without having to checkout/switch to that branch. It turns out git show can do that!
Say I'm on branch-a, but I want to see the latest commit I made on branch-b. It's actually really straightforward:
$ git show branch-b
This follows a lot of the git norms, too! git show branch-b~ will show the previous commit on branch-b (and git show branch-b~2 the commit before that). To view a single file in that commit, git show branch-b:path/to/file.rb!
In Javascript you can group together console logs by using console.group()
This will output all of the following console logs in a nicer indented form.
console.group("Food");
console.log("Apple");
console.log("Banana");
console.log("Cookie");
You can nest groups inside of one another. To end a group just call console.groupEnd()
// ✨ indented for a better visual experience ✨
console.group("Food");
console.group("Fruit");
console.log("Apple");
console.log("Banana");
console.groupEnd();
console.group("Dessert");
console.log("Cookies");
console.groupEnd();
console.groupEnd();
So in order to do an "upsert" we use an INSERT command with a CONFLICT statement. Then if we need to do some conditional setting in the case of existing data then we can use the "temp table" EXCLUDED that PostgreSQL provide to us. They have a nice example how to use that in their docs and here's mine example:
INSERT INTO users AS u (email, fullname) VALUES
('darth@example.com', 'Darth Vader'),
('luke@example.com', 'Luke Vader')
ON CONFLICT (email) DO UPDATE
SET fullname = EXCLUDED.fullname || ' (formerly known as ' || u.fullname || ')';
For this to work we have to have an unique constraint on the column email and the outcome of this could be:
SELECT email, fullname
FROM users;
| email | fullname |
| --- | --- |
| darth@example.com | Darth Vader |
| luke@example.com | Luke Vader (formerly known as Luke Skywalker) |
It's very simple to jump to a specific line. Simply press ctrl+g. This will open a prompt where you just type in your desired line number and hit enter.
Today I learned how to check in git if a branch exists on my local repo. I bounce between projects that use a main or master branch and wanted to automate away checking which to use.
git show-ref lists references in a local git repository. It can show any ref, be it tag or branch or whatever. But we want to use it for branches:
# let's say this repo has `main` branch, not `master`
$ git show-ref --branches master
$ git show-ref --branches main
2067645fb4d7b6ab07215c025dee95b872150db2 refs/heads/main
Note it's important to filter by branches, otherwise you can get false positives from remotes or tags
$ git show-ref main
2067645fb4d7b6ab07215c025dee95b872150db2 refs/heads/main
2067645fb4d7b6ab07215c025dee95b872150db2 refs/remotes/origin/main
You can use the existence of output from this command in scripts to, for example, determine which branch to rebase against:
#!/bin/sh
main_exists=`git show-ref --branches main`
if [ -n "$main_exists" ]; then
branch="main"
else
branch="master"
fi;
git rebase -i $branch
You can tell eslint to ignore multiple lines like this
/* eslint-disable */
// ignore any rules on this line
/* eslint-enable */
You can also pass a specific rule to ignore.
/* eslint-disable quotes */
console.log('non eslint friendly quotations will be ignored on these lines...')
/* eslint-enable quotes */
Sometimes you need to spin up a rails app using an older version of rails. Running rails new will spin up an app with the latest version (which is what you want most of the time). But if you have older gems of rails installed you can create new rails apps by specifying the version wrapped in underscores.
Say your rails entry in your gem list looks like this: rails (7.2.2.2, 7.2.1, 7.1.5.2, 7.1.2, 7.0.8.7). If you want to create a new rails app using 7.0.8.7, you can run (_ before and after the version number!):
$ rails _7.0.8.7_ new new_app
And boom, you've got a new_app created running rails 7.0.8.7.
With ActiveSupport you can easily add months (or days, years, etc) to a date with:
pry(main)> Date.today
# => Fri, 05 Sep 2025
pry(main)> Date.today + 2.months
# => Wed, 05 Nov 2025
pry(main)> Date.today - 1.month
# => Tue, 05 Aug 2025
But what if you're working outside of Rails and without ActiveSupport? You can use the shovel (<<) operator on dates to return the date n months earlier.
pry(main)> Date.today
# => Fri, 05 Sep 2025
pry(main)> Date.today << 1
# => Tue, 05 Aug 2025
If you want to go forwards, you can use >>, or negate the value of n using <<:
pry(main)> Date.today
# => Fri, 05 Sep 2025
pry(main)> Date.today >> 2
# => Wed, 05 Nov 2025
pry(main)> Date.today << -2
# => Wed, 05 Nov 2025
Sometimes there are variables I want to initialize or setup I want to run each time I enter a rails console, and I don't want to have to type it out every time. I'm using pry-rails, so my rails console is a pry session, and I can add ruby code to my .pryrc file to be run on console startup. Conveniently, this runs after the environment is loaded, so I have access to all my ActiveRecord models.
# .pryrc
author = Author.find(1)
If I put the above in my .pryrc, then I've got author available to me whenever I'm in a rails console (but not when I drop into a pry session in rails server (which is fine, I think it's less useful there)).
You can use a local .pryrc in your project's directory, or a global config in ~/.pryrc.
Today I learned you can add suffixes to ActiveRecord Enums. I knew it was possible to prefix enums with the _prefix option:
class Answer < ApplicationRecord
enum selection: {yes: "yes", no: "no", idk: "i don't know"}, _prefix: true
end
And you get helper methods like answer.selection_yes?, but that reads a little awkwardly. I think it reads better as answer.yes_selection?. Turns out you can do this with _suffix:
class Answer < ApplicationRecord
enum selection: {yes: "yes", no: "no", idk: "i don't know"}, _suffix: true
end
answer = Answer.new selection: "yes"
answer.yes_selection? # => true
answer.no_selection? # => false
Luxon’s .hasSame lets you easlity check if two DateTimes contain the same specified time unit (such as year, month, or day).
import { DateTime } from "luxon";
const a = DateTime.local(2025, 8, 15, 10);
const b = DateTime.local(2025, 8, 15, 22);
a.hasSame(b, "day");
// true
a.hasSame(b, "hour");
// false
a.hasSame(b, "month");
// true
You can get git branch auto-completion in bash. Sometimes this is configured out of the box, but it didn't work for me using homebrew's git.
If you are using git installed via homebrew, git-completions.bash is located at /opt/homebrew/etc/bash_completion.d/git-completions.bash (or better yet $(brew --prefix)/etc/bash_completion.d/git-completions.bash for reliability). You just need to source it in your .bashrc or .bash_profile with:
test -f $(brew --prefix)/etc/bash_completion.d/git-completion.bash && . $_
(This is a cool shorthand syntax to test that the file exists, and if it does, source it. $_ refers to the last argument in the previous command, in this case the full path to git-completion.bash)
Now you can tab complete all your branch names in git checkout, git rebase, and more!
You can use as const in typescript to restrict an object's types.
const status = {
SUCCESS: 'success',
ERROR: 'error',
LOADING: 'loading',
} as const;
Without using as const, both the keys and values of the object would be string types, but
with as const, the value types are the exact literals:
"success" | "error" | "loading"
We can create a type of string literals that comes from an array if we add the as const modifier to the array. This way:
const COLORS = ["red", "blue", "green"] as const;
type Color = typeof COLORS[number];
This way the type Color will be inferred as either "red", "blue" or "green". If you remove the as const then the type Color will be a string.
In Rails 7.1, attribute normalization was introduced. This gives us an easy way to clean up data before persistence, or other actions.
class Contact < ApplicationRecord
normalizes :phone, with: -> (phone) { phone.gsub(/\D/, "") } # remove non-number chars
end
The above ensures that before save, a phone number like 904-123-4567 gets converted to 9041234567.
In Rails 8, attribute normalization was backported to ActiveModel. So you can also use these methods in ActiveModels (re: Form objects) -
class ContactForm
include ActiveModel::Attributes
include ActiveModel::Attributes::Normalization
attribute :phone
normalizes :phone, with: -> (phone) { phone.gsub(/\D/, "") }
end
contact = ContactForm.new
contact.phone = "904-123-4567"
contact.phone # 9041234567
For what it's worth, I didn't know that symbols in Ruby can also be strings.
For example:
:"foo bar"
=> :"foo bar"
:"foo bar".class
=> Symbol
Thanks, Exercism.
Today I learned that you can combine preload with join in Ecto to fetch related data in a single query instead of making multiple database trips.
For example, instead of doing this:
from(
u in User,
where: u.status == :active,
preload: [:emails]
) |> Repo.all()
Which runs 2 queries in db, you can do this in a single query:
from(
u in User,
join: e in assoc(u, :emails),
where: u.status == :active,
preload: [emails: e]
) |> Repo.all()
Today I Learned about a new way to list the errors for an invalid ActiveRecord model. Let's say I have a blog post class with title and author attributes, both of which are required:
class BlogPost < ApplicationRecord
validates :title, presence: true
validates :author, presence: true
end
Normally I interact with the errors in an invalid model through the nice ActiveModel Errors interface:
pry(main)> blog_post = BlogPost.new
pry(main)> blog_post.valid?
pry(main)> blog_post.errors
# => <ActiveModel::Errors [#<ActiveModel::Error attribute=title, type=blank, options={}>, #<ActiveModel::Error attribute=author, type=blank, options={}>]>
pry(main)> blog_post.errors.where(:title)
# => [#<ActiveModel::Error attribute=title, type=blank, options={}>]
But you can also return a hash of attributes containing arrays of their error details and use your favorite hash methods:
pry(main)> blog_post.errors.details
# => {:title=>[{:error=>:blank}], :author=>[{:error=>:blank}]}
pry(main)> blog.errors.details.dig(:title, 0, :error)
# => :blank
Today I learned that you can use a dash - with git rebase to quickly rebase your current branch onto the previous branch you were on. This is a handy shortcut if you’re hopping between branches and want to rebase without typing the full branch name.
For example, after switching between branches:
git checkout main
git pull --rebase
git checkout new-feature-branch
git rebase -
The - here ^ refers to the last branch you were on (main in this case), so this command is equivalent to git rebase main.
It's funny that I used this all the time with git checkout but it never occurred to me that I could use for other git commands.
Rails includes a handy method on Date to construct a range with all days in the current week.
> Date.parse("2025-07-18").all_week
=> Mon, 14 Jul 2025..Sun, 20 Jul 2025
https://api.rubyonrails.org/classes/DateAndTime/Calculations.html#method-i-all_week
Today I Learned you can use brace expansion to rename files in the command line (it works in both bash and zsh).
Brace expansion allows you to generate strings sharing a common prefix or suffix - perfect for moving/renaming files:
To copy someFile.js to someFile.ts, you can run:
$ cp someFile.{js,ts}
# expands to:
$ cp someFile.js someFile.ts
To rename app/model/blog_test.rb to app/model/blog_spec.rb:
$ mv app/model/blog_{test,spec}.rb
# expands to:
mv app/model/blog_test.rb app/model/blog_spec.rb
If you're developing an Android app and you want to use a real device instead of the emulator then you can use scrcpy:
scrcpy --stay-awake
It's faster than the emulator and you can interact with your computer's mouse & keyboard with the Android device.
In VS Code if you're leftside panel is set to something else and you want to quickly jump to the file tree view without leaving the safety of your keyboard, just press CMD+Shift+E and voila you can now see the filetree for the file you're currently viewing.
Thanks, Vinicius Negrisolo
When running tests in Elixir, if you only want to rerun the failed tests, just pass in --failed
mix test --failed
Today I learned you can see which processes have a file open with fuser. For example, if I wanted to see what process was writing to log/development.log in my rails app, I'd run
$ fuser log/development.log
log/development.log: 76170
So the process with PID 76170 has the file open. Running ps will show me the process details:
$ ps 76170
PID TT STAT TIME COMMAND
76170 s008 S+ 0:02.86 ruby bin/rails console
Turns out I had a rails console running!
You could also turn this into a one-liner with xargs:
$ fuser log/development.log | xargs ps