Generated columns in Rails 7
Rails 7 now supports a feature that was shipped in Postgres 12 called generated columns that can be handy when you want to transform columns on a table for convenience. For example, you might want to concatenate a user’s first and last names to generate a `full_name` column that you can use in your codebase and perform searches against.
Note, you can only use columns that exist on the same table in the computation of your generated column. Referencing foreign keys or other generated columns is not possible.
There are two different types of generated columns:
Virtual (computed at read)
Stored (computed and cached at write – create/update)
In this case, let’s created a stored generated column that caches the user’s full name when those columns are updated.
class AddFullNameToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users,
:full_name,
:virtual, # declaring a virtual column
type: :text, # what type the virtual column will return
as: "first_name || ' ' || last_name", # computation
stored: true # storing the value on create/update
end
end
[1] pry(main)> user = User.first
=> #<User:0x000000010e69f050
id: 1,
first_name: "Jane",
last_name: "Doe",
full_name: "Jane Doe">
[2] pry(main)> user.update(first_name: "Jane")
=> true
[3] pry(main)> User.first
=> #<User:0x000000010e91eb00
id: 1,
first_name: "Jill",
last_name: "Doe",
full_name: "Jill Doe"> # new value for full_name as well
And there we have it! A user now has a full_name
column that stays in sync with its dependencies. What a wonderful time it is to be a Rails and Postgres user these days.