Adding a new column with Rails migrations
Posted: 2018-02-22
Given a table of records you’re adding a new column to, e.g.
class AddSourceToStatusEvents < ActiveRecord::Migration[5.1]
def change
add_column :status_events, :event_source, :string, null: true
end
end
If you define with:
null: true, default: 'anything'
It will add the new column and backfill existing records with 'anything'
null: false, default: 'anything'
Again, it will add the new column and backfill existing records with 'anything'
null: false # but no default
Then the result is:
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::NotNullViolation: ERROR: column "event_source" contains null values
Next if you want to define a default that only makes sense for new records you will need a way to leave the existing records with NULL
.
Easy. Define the new column without a default and allow NULL
. Then modify the column again to specify the default for all new records:
class AddSourceToStatusEvents < ActiveRecord::Migration[5.1]
def change
# Add column, allowing all existing records to take the value NULL
add_column :status_events, :event_source, :string, null: true
# Now change the default so all future records have a value
change_column_default :status_events,
:event_source,
from: nil, to: 'local'
end
end