Adding a new column with Rails migrations

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