Generate migrations (database or data)
Each ActiveRecord model must have a database table. Database tables are created and modified by migrations.
A migration is a Ruby class that inherits from the current Rails migration version and is located in the db/migrate directory. For the current application version, use ActiveRecord::Migration[8.1].
When Rails is upgraded, use the version generated by rails g migration ... for new migrations instead of copying an older migration superclass.
Class naming: Action + ModelClassName — e.g. CreateMyModel or AddMyColumnToMyModel.
Method: Use a single change method. The older two-method format (up / down) may appear in legacy code.
Filename Timestamp Format
Migration filenames follow this convention:
The timestamp is generated via Time.now.utc.strftime("%Y%m%d%H%M%S"), producing a 14-digit UTC timestamp.
IMPORTANT for agents: Never use placeholder timestamps like
20210101000000. Always use a realistic current UTC timestamp.
Example breakdown for 20240502101659:
| Part | Value | Meaning |
|---|---|---|
2024 |
YYYY | Year |
05 |
MM | Month |
02 |
DD | Day |
10 |
HH | Hour (24h, UTC) |
16 |
MM | Minute |
59 |
SS | Second |
Example filename:
Creating a new migration
The strongly recommended way is to use the rails generator:
This creates db/migrate/20240502101659_create_my_model.rb with:
class CreateMyModel < ActiveRecord::Migration[8.1]
def change
create_table :my_models do |t|
t.belongs_to :author, null: false
t.belongs_to :collection, null: true
t.string :name, null: false
t.text :description, null: false
t.integer :status, null: false, index: true
t.timestamps
end
end
end
Indexing
Columns used for search should be indexed. Define indexes inline:
or explicitly with add_index:
Using an existing table
In some specific cases an existing table may be reused. In that case, the table name is specified in the model definition.
Changing an existing table
Never alter a migration after it has been executed. Always create a new migration for any change. Example:
Generated migration:
class RemoveDescriptionFromMyModels < ActiveRecord::Migration[8.1]
def change
remove_column :my_models, :description, :text
end
end
Before release
Before the first release of a new model, all migrations created during development must be merged into a single migration that creates the table with all columns.
Development period best practice
When a model changes frequently during development, use force: true on create_table to drop and recreate the table on each migration run:
Tip: To force re-execution of a migration in an already-migrated environment, increment the timestamp by 1 second. Example:
20240502101659_create_my_model.rb→20240502101700_create_my_model.rb
Data migration
Data migrations modify existing data in the database. They are located in the db/data directory and follow the same filename convention as DB migrations.
Data migrations inherit from EasyExtensions::EasyDataMigration and must implement both up and down methods.
Use cases:
- Prepare data before first release
- Alter existing data when a significant change is introduced