Rails 7 brings a host of new features and improvements, making it even easier to build robust and maintainable web applications. One of the powerful features available in Rails is the ability to create virtual (or computed/generated) columns in your database tables. In this blog post, we’ll explore how to create a virtual column in Rails 7 along with detailed explanations and examples.
What Are Virtual Columns?
Virtual columns are database columns that are not directly stored but computed based on expressions involving other columns. They can be particularly useful for derived data, such as concatenations, calculations, or transformations that should always be consistent with the source data.
Example Scenario
Let’s say we have a PersonalDocuments table, and we want to add a full_name column that stores a person’s full name and a virtual column full_name_length that calculates the length of the full_name.
Creating the Migration
To create the PersonalDocuments table with the required columns, we will use the create_table migration method. Here’s how you can do it:
Migration
1
2
3
4
5
6
7
8
9
10
class CreatePersonalDocuments < ActiveRecord::Migration[7.0]
def change
create_table :personal_documents do |t|
t.string :full_name
t.virtual :full_name_length, type: :integer, as: "length(full_name)", stored: true
t.timestamps
end
end
end
In this migration:
create_table :personal_documentscreates a new table namedpersonal_documents.t.string :full_nameadds afull_namecolumn to the table.t.virtual :full_name_length, type: :integer, as: "length(full_name)", stored: trueadds a virtual columnfull_name_lengththat calculates the length of thefull_namecolumn.
The stored: true option ensures that the value of full_name_length is calculated when the row is inserted or updated and stored in the database. This makes querying more efficient as the value doesn’t need to be recalculated each time it is accessed.
Updating the Model
In your PersonalDocument model, no special configuration is needed for the virtual column. It will be available as a read-only attribute.
Model
1
2
3
class PersonalDocument < ApplicationRecord
# Any other model logic
end
Using the Virtual Column
You can now use the full_name_length virtual column just like any other attribute. Here’s an example of how to create a record and access the virtual column:
Usage
1
2
personal_document = PersonalDocument.create(full_name: "John Doe")
puts personal_document.full_name_length # Outputs: 8
Important Considerations
- Stored vs. Virtual: The
stored: trueoption makes the column a “stored generated” column, meaning its value is calculated when the row is inserted or updated and stored in the database. If you want it to be recalculated on the fly every time it is accessed, you can usestored: false(though support for this varies by database).
Verifying the Setup
After running the migration, you can verify the columns with the following Rails console commands:
1
2
3
4
rails db:migrate
rails console
personal_document = PersonalDocument.create(full_name: "Jane Doe")
puts personal_document.full_name_length # Should output: 8
This setup ensures that whenever the full_name is updated, the full_name_length virtual column is automatically recalculated and stored.