How to combine "change", "up", and "down" in a Rails migration
Rails migrations allow you to use a change method whose calls are automatically inverted for the down path. However, if you need to some path-specific logic (like SQL UPDATE statements) you can not define up and down methods at the same time.
If you were to define define all 3 of them, Rails would only run change and ignore up and down. However, Rails 4+ features a helper method called reversible:
class MyMigration < ActiveRecord::Migration
def cha...
Generating an Entity Relationship Diagram for your Rails application
This card explains how to generate an entity relationship diagram for your Rails application.
We also show how to limit your ERD to a subset of models, e.g. models inside a namespace.
Generating a full ERD
Option A: RubyMine
- Right-click anywhere in your project tree
- In the context menu, find the "Diagrams" menu item at/near the bottom
- Inside, choose "Show diagram" → "Rails Model Dependency Diagram"
- A new tab will open with the diagram inside. You can modify it there, and export it as an image.
Option B: Use rails-e...
Understanding race conditions with duplicate unique keys in Rails
validates_uniqueness_of is not sufficient to ensure the uniqueness of a value. The reason for this is that in production, multiple worker processes can cause race conditions:
- Two concurrent requests try to create a user with the same name (and we want user names to be unique)
- The requests are accepted on the server by two worker processes who will now process them in parallel
- Both requests scan the
userstable and see that the name is available - Both requests pass validation and create a user with the seemingly available name...
How to organize large I18n dictionaries in Ruby on Rails
If you're suffering from a huge de.yml or similiar file, cry no more. Rails lets you freely organize your dictionary files in config/locales.
My organization works like this:
-
config/locales/rails.de.ymlmodified Rails boilerplate -
config/locales/faker.de.ymlmodified Faker boilerplate -
config/locales/models.de.ymlmodel names, attribute names, assignable_value labels - `config/locales/views.de.y...
How to make your application assets cachable in Rails
Note: Modern Rails has two build pipelines, the asset pipeline (or "Sprockets") and Webpacker. The principles below apply for both, but the examples shown are for Sprockets.
Every page in your application uses many assets, such as images, javascripts and stylesheets. Without your intervention, the browser will request these assets again and again on every request. There is no magic in Rails that gives you automatic caching for assets. In fact, if you haven't been paying attention to this, your application is probabl...
How to Work With Time Zones in Rails
When dealing with time zones in Rails, there is one key fact to keep in mind:
Rails has configurable time zones, while
Ruby is always in the server's time zone
Thus, using Ruby's time API will give you wrong results for different time zones.
"Without" time zones
You can not actually disable time zones, because their existence is a fact. You can, however, tell Rails the only single time zone you'll need is the server's.
config.time_zone = "Berlin" # Local time zone
config.active_record.default_timezone = :loca...
Rails route namespacing (in different flavors)
TL;DR There are three dimensions you can control when scoping routes: path helpers, URL segments, and controller/view module.
scope module: 'module', path: 'url_prefix', as: 'path_helper_name' do
resources :examples, only: :index
end
as → prefixes path helpers: path_helper_name_examples_path and path_helper_name_examples_url
path → prefixes URL segments: /url_prefix/examples
module → nests the controller: controller Module::ExamplesController, found at app/controllers/module/examples_controller.rb with views ...
Rails: Handling actions that need to happen after all transactions
In Rails 7.2. the feature ActiveRecord.after_all_transactions_commit was added, for code that may run either inside or outside a transaction (we have a special card for nested transactions in general) and needs to perform work after the state changes have been properly persisted. e.g. sending an email.
Example
def publish_article(article)
article.update(published: true)
ActiveRecord.after_all_transactions_commit do
PublishNotification...
Rails I18n fallback locales
When you need to create a locale for a language variant (like Austrian for German), you probably don't want to duplicate your entire de.yml file only to change a few minor exceptions for our Austrian friends.
Luckily, the I18n gem used by Rails has a fallback feature where you can make one locale file fall back to another if no translation is available.
In the example above you would have a config/locales/de_DE.yml:
de_DE:
# hundreds of translations here
... and another...
Rails I18n scope for humanized attribute names
ActiveModel classes have a class method .human_attribute_name. This returns a human-readable form of the attribute:
Person.human_attribute_name(:first_name) # => "First name"
By default Rails will use String#humanize to format the attribute name, e.g. by replacing underscores with spaces and capitalizing the first word. You can configure different translation in your I18n locales, e.g. in config/locales/en.yml:
en:
activerecord:
attributes...
Rails: Redirecting the Logger output temporary aka showing Rails logs in the console
Most of the time, when you are interested in any log output,
- you see the logs directly on your console
- or you tail / grep some logfile in a separate terminal window
In rare cases it's helpful to redirect the Logger output temporary to e.g. STDOUT.
Rails.logger = Logger.new(STDOUT)
ActiveRecord::Base.logger = Logger.new(STDOUT)
User.save!
#=> D, [2025-09-08T11:12:26.683106 #1094157] DEBUG -- : User Load (1.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]]
Many frameworks in Rails ...
Rails: Configuring the default sorting behaviour
In Rails, the implicit_order_column (added in Rails 6) is a configuration option that helps you define the default sorting behavior of ActiveRecord queries when no explicit ORDER BY clause is provided. This option allows you to specify a column that Rails will use to automatically sort records in a particular order when no specific ordering is given.
Since the id is typically the primary key and automatically indexed, Rails will default t...
How to debug file system access in a Rails application
It might sometimes be useful to check whether your Rails application accesses the file system unnecessarily, for example if your file system access is slow because it goes over the network.
The culprit might be a library like carrierwave that checks file existence or modification times, whereas your application could determine all this from your database.
Introducing strace
One option it to use strace for this, which logs all system calls performed by a process.
To do this, start your rails server using something like
DISA...
Rails disables CSRF protection in tests
The default configuration of Rails disables CSRF protection in tests. If you accidentally forget to send the CSRF token for POST requests, your tests will be green even though your application is broken.
You probably want to enable CSRF protection in tests that can speak JavaScript.
For RSpec...
Sentry Local Logging in Ruby
Enable local logging for Sentry when:
- Debugging Sentry event capture locally
- Testing error handling without polluting production metrics
- Developing background jobs and want to see what Sentry captures
How to enable
To capture and log Sentry events locally during development without sending to the server, add this to config/initializers/sentry.rb inside the Sentry.init block:
if Rails.env.development?
# Use dummy transport to prevent actual transmission to Sentry
config.transport.transport_class = Sentry::DummyTran...
Auto-generating plain-text bodies for HTML e-mails in Rails apps
When building an application that sends e-mails to users, you want to avoid those e-mails from being classified as spam. Most obvious scoring issues will not be relevant to you because you are not a spammer.
However, your application must do one thing by itself: When sending HTML e-mails, you should include a plain-text body or tools like SpamAssassin will apply a significant score penalty. Here is how to do that automatically.
- Add
premailer-railsto yourGemfileandbundle. - Done! ...
Rails 8: The db:migrate task might not run all migrations in db/migrate/ anymore
In Rails 8 the behavior of the rails db:migrate command has changed for fresh databases (see PR #52830).
- Before Rails 8: The command runs all migrations in the folder
db/migrate/* - After Rails 8: The command loads the schema file (
db/schema.rbordb/structure.sql) if existing and runs all pending migrations in the folderdb/migrate/*afterwards
This speeds up the command. But e.g. migrations with data manipulations are missing.
The only way to run all pending mig...
Rails and Postgres: How to test if your index is used as expected
This is a small example on how you can check if your Postgres index can be used by a specific query in you Rails application. For more complex execution plans it might still be a good idea to use the same path of proof.
1. Identify the query your application produces
query = User.order(:last_name, :created_at).to_sql
puts query
# => SELECT "users".* FROM "users" ORDER BY "users"."last_name" ASC, "users"."created_at" ASC
2. Add an index in your migration and migrate
add_index :users, [:last_name, :created_at]...
Rails credentials: Always use the bang version
Rails credentials are a way to store secrets in an encrypted YAML file. Usage is simple: each key in the credentials file becomes a method on Rails.application.credentials, returning the corresponding secret.
# Credentials file
file_storage_secret: superstrongsecret
# Somewhere in the application
FileStorage.secret = Rails.application.credentials.file_storage_secret
Since credentials usually are different between environments, you can easily forget to define them for another environment. If it is an API token, you'll...
Ruby / Rails: clone vs. dup vs. deep_dup
Ruby and Rails have several methods for creating a new object that looks like another: clone, dup, deep_dup. When using them you should be aware of their differences so that you can select the method you really need.
clone
- Shallow copy: references to other objects/values are copied (instead of cloning those objects/values)
- Clones the object and all its "special object attributes" like
frozen,taintedand modules that the object has been extended with - [Ruby 2.6 documentation for clone](https://devdocs.io/ruby~2.6/obj...
Guide to localizing a Rails application
Localizing a non-trivial application can be a huge undertaking. This card will give you an overview over the many components that are affected.
When you are asked to give an estimate for the effort involved, go through the list below and check which points are covered by your requirements. Work with a developer who has done a full-app localization before and assign an hour estimate to each of these points.
Static text
- Static strings and template text in
appmust be translated: Screens, mailer templates, PDF templates, helpe...
Rails npm packages will use an uncommon versioning scheme
When Rails releases a new version of their gems, they also release a number of npm packages
like @rails/activestorage or @rails/actioncable.
Unfortunately Rails uses up to 4 digits for their gem version, while npm only allows 3 digits and a pre-release suffix.
To map gem versions and npm versions, Rails is going to use a naming scheme like this:
| Gem version | npm version |
|---|---|
7.0.0 |
7.0.0 |
7.0.1 |
7.0.100 |
| ... |
Checklist: Using Carrierwave in a Rails project
This checklist should help you to check edge cases that are not part of the default Carrierwave configuration.
- Check Default Configuration and Suggested Changes
- Use secret URLs.
- Check if you need expiring public URLs.
- Check if you need an optimized cache
- Use a [nested directory structure](https://makandracards.com/m...
A simple example with a GIN index in Rails for optimizing a ILIKE query
You can improve your LIKE / ILIKE search queries in PostgreSQL by adding a GIN index with an operate class ("opclass") to split the words into trigrams to the required columns.
Example
class AddSearchTextIndexToUsers < ActiveRecord::Migration[7.1]
def change
enable_extension 'pg_trgm'
add_index :users, :search_tex...