Using FactoryBot in Development
If you need dummy data to play around with in development, it's often faster to reuse your existing factories instead of using the UI or creating records in the Rails console. This approach saves time and gives you useful defaults and associations right out of the box.
You can use FactoryBot directly in the Rails console like this:
require 'factory_bot_rails' # Not needed if the factory_bot_rails gem is in the :development group
FactoryBot.create(:user)
You can also apply traits or override attributes:
FactoryBot.create...
How to apply transparency to any color with pure CSS
To apply transparency to an element, you can use opacity in CSS. However, sometimes you don't want to make the entire element transparent, only a color.
Using not-so-modern CSS, you can simply generate non-opaque versions of a color. This card describes how to do that.
Note that we're not talking about defining colors with transparency. This is about the case where you have a color but need a more transparent variant of it (e.g. for a border, background, etc.), and where your component does that without defining the transparent variant ...
How to invert currentColor with pure CSS
The currentColor CSS keyword references the current text color and can be used to apply an element's text color to other properties.
Using modern CSS, you can also use it to calculate colors from it. This card describes how to invert currentColor, but you can use this technique for other calculations as well.
How to invert currentColor
They key is CSS' hsl() function and from keyword for it:
--inverted-color: hsl(from ...
Selecting the nth element matching a selector
The :nth-child pseudo class is commonly used for targeting elements based on their position within a parent container, for example the third element in a list or every even-numbered item. However, :nth-child can do more.
In modern CSS specifications (Level 4), there’s an additional feature that lets you use :nth-child in combination with a list of css selectors. This way, you can ta...
Git Rebase: How to squash/fixup/edit/... commits without actually rebasing (keeping the base)
Purpose:
Interactively rebase your current branch onto main, keeping the original base commit (i.e. not rebasing onto main directly).
Use Case:
Useful when you've branched off a long-lived feature branch and want to clean up your commits without changing the original base. Afterwards you will be able to rebase one clean commit interactively onto main without going through each commit individually using git rebase -i main.
What it does:
- Opens an interactive rebase UI to choose squash/edit/fixup for each co...
Prevent unnecessary automated back-and-forth when sending noreply-emails
When you send automated emails from a noreply@-address, and the recipient has an out of office enabled, the autoreply bounces and they get an additional email with an error message.
To prevent the recipient's auto-response and the following error message you can set the email header Auto-Submitted: auto-generated in your mailer, for example like this:
class NoReplyMailer < ApplicationMailer
default from: 'noreply@yourapp.com', 'Auto-Submitted' => 'auto-generated'
end
Testing Accessibility using Orca
Orca is a Linux screen reader. Since it is part of the GNOME project it should come preinstalled with Ubuntu installations.
Getting started
To turn on the screen reader you can either go to Settings > Accessibility and then activate Screen Reader in the "Seeing" section or you can simply type orca in your terminal. Alternatively you can use the default keyboard shortcut super + alt + s to toggle the screen reader.
Note
It may feel quite strange in the beginning to use a screen reader. It is constantly commenting on everyth...
How to set Chrome's time zone in Selenium tests
For Selenium tests, your browser starts in your local timezone, or whatever your system's environment specifies.
This is usually good enough. To test any timezone-dependent behavior in Chrome, you can change the time zone using the Chrome DevTools Protocol.
Example
Chrome accepts any IANA time zone name, like "Europe/Berlin" or "Asia/Tokyo".
Here is the relevant command for Capybara:
page.driver.browser.execute_cdp('Emulation.setTimezoneOverride', timezoneId: 'Asia/Tokyo')
``...
Rails: Keeping structure.sql stable between developers
Why Rails has multiple schema formats
When you run migrations, Rails will write your current database schema into db/schema.rb. This file allows to reset the database schema without running migrations, by running rails db:schema:load.
The schema.rb DSL can serialize most common schema properties like tables, columns or indexes. It cannot serialize more advanced database features, like views, procedures, triggers or custom ditionaries. In these cases you must switch to a SQL based schema format:
# in application.rb
config.a...
A "text-wrap: balance" fallback approach
Here is a workaround for when you want to use text-wrap: balance but must also render nicely for browsers that don't support it (mostly Safari <17.5).
Step 1: Put some <br>s into your HTML
First, place explicit line breaks that should work for most cases.
This depends on your use case and is affected by e.g. container widths or user content.
<div class="my-element">
<p>
Average score
<br>
...
Implementing upload progress and remove button with ActiveStorage DirectUpload
DirectUpload allows you to upload files to your file storage without having to wait for the form to submit. It creates AJAX requests to persist the file within your form and wraps them in a little API. This card will show you how to use it in order to create in-place file uploads with progress and a remove button.
This is basic functionality, you may add additional elements, styles and logic to make this look fancy, but the core functionality is the same. I created a file upload that looks like this:

const svgo = require('svgo')
const options = {
// ...
loader: {
// ...
'.svg': 'copy', // this may be different...
Rails: Using PostgreSQL full-text search without a gem
PostgreSQL can cosplay as a full-text search engine. It doesn't have the features or fidelity of ElasticSearch or Algolia, but it's good enough if you just need to search and rank large volumes of text.
This card will teach you how to index, search and rank your Rails models in a PostgreSQL full-text index. We will do this without using any gems aside from ActiveRecord. While there are gems like pg_search or pg_fulltext, manual integration requires very...
RSpec: Executing specs by example id (or "nesting index")
There are several ways to run a single spec. I usually copy the spec file path with the line number of the example and pass it to the RSpec binary: bin/rspec spec/models/user_spec.rb:30 (multiple line numbers work as well: :30:36:68). Another is to tag the example with focus: true or to run the example by matching its name.
In this card I'd like to ...
Using Low-Level Prompts for High-Accuracy AI Coding
The key to unlocking the full potential of LLMs in coding lies in crafting precise prompts. The main challenge is learning how to structure prompts effectively to guide the model toward accurate results. Further evidence supporting this is the fact that Aider already writes ~70% of its own code (as of 02/2025). However, when starting out, your results may fall short of efficiently generating large portions of your code with the...
How to use your favorite font in Slack
In Slack, the settings dialog only offers a fixed selection of fonts. You can use any font you like using the /slackfont command.
Fonts need to be installed on your machine. Webfonts beyond those provided by Slack won't magically work unless you install them locally.
Only the chat font can be changed. The monospaced font used for code blocks isn't easily customizable.
Example usage
-
/slackfont Comic Neueto use "Comic Neue" (if installed) -
/slackfont system-uito use your desktop's system font in Slack. -
/slackfont(withou...
Rails: Accessing strong parameters
Rails wraps your parameters into an interface called StrongParameters. In most cases, your form submits your data in a nested structure which goes hand in hand with the strong parameters interface.
Example:
curl -X POST -d "user[name]=bob" https://example.com/users
class UsersController
def create
User.create!(params.expect(user: [:name])) # Or User.create!(params.require(:user).permit(:name))
end
end
This works well most of the time...
Rails 8 introduces `params.expect`
The new params.expect method in Rails 8 improves parameter filtering, addressing issues with malformed input and enhancing security. It provides a cleaner, more explicit way to enforce the structure and types of incoming parameters.
What changed
-
Replaces
requireandpermit: Combines both methods for concise parameter validation. - Explicit Array Handling: Requires double array syntax to define arrays of hashes, improving clarity.
- Enhanced Validation: Ensures expected parameter structure, rejecting malformed input wi...
Specify Gemfile for bundle
Bundler allows you to specify the name of the Gemfile you want to bundle with the BUNDLE_GEMFILE environment variable.
BUNDLE_GEMFILE=Gemfile.rails.7.2 bundle
By default, bundler will look for a file called Gemfile in your project, but there may be cases where you want to have multiple Gemfiles in your project, which cannot all be named Gemfile. Let's say for example, you maintain a gem and want to run automated tests against multiple rails versions. When you need to bundle one of your secondary Gemfiles, the solution above ...
Reverse lookup a fixture name by its id and table name
To reverse lookup a fixture by its table name and id, use the following approach on ActiveRecord::FixtureSet:
table = 'users' # Specify the fixture table name
id = 123122 # Specify the ID to look for
# Find the fixture that matches the given ID
ActiveRecord::FixtureSet.all_loaded_fixtures[table].fixtures.find { |key, value| value['id'] == id }
Result Example:
[
"one", # Fixture name
#<ActiveRecord::Fixture:0x00007e79990234c8>, # ActiveRecord::Fixture object
@fixture= { ... }, # The raw fixtu...
Rails: Looking up constants by their name string
TL;DR: Rails ships two methods to convert strings to constants, constantize and safe_constantize. Neither is safe for untrusted user input. Before you call either method you must validate the input string against an allowlist. The only difference between the two methods is that unresolvable constants raise an error with constantize, but return nil with safe_constantize. If you validate the input string against an allowlist, an error should never happen.
Preventing Dangerous Lookups
Suppose an application uses eit...
How to disable logging for ActiveStorage's Disk Service routes
In development, we store files using ActiveStorage's disk service. This means that stored files are served by your Rails application, and every request to a file results in (at least!) one non-trivial log entry which can be annoying. Here is how to disable those log entries.
Example
Here is an example of what loading a single <img> in an example application writes to the Rails log.
Started GET "/rails/active_storage/blobs/redirect/..." for ::1 at ...
Processing by ActiveStorage::Blobs::RedirectController#show as SVG
Parameter...
How the Date Header Affects Cookie Expiration and Caching
tl;dr
When a cookie includes an
Expiresattribute or an HTTP response includes caching headers likeExpiresorCache-Control, their validity depends on the server'sDateheader if present. Otherwise, the browser uses its local time. This can lead to issues in tests with mocked time or inconsistent cache behavior.
Cookie Expires depends on the Date header or browser time
When a cookie includes an Expires attribute, the browser evaluates the expiration date relative to a reference time:
- If the HTTP response ...