Search code examples
rubyruby-on-rails-4activerecordrails-migrationsruby-on-rails-4.2

Specifying default value from lambda in a migration


I want to add a non-null column unique_id to some of my models. The implementation for this would basically be SecureRandom.hex(8). Is there a way to specify this in the migration itself, such that it computes the default values for all the older rows.

Maybe something like this:

add_column :users, :unique_id, :string, null: false, default: proc { generate_unique_id }.call

The problem is, the above method will generate unique_id only once (which is kind of expected). Is there a way to specify for generating default for every row?


Solution

  • This is not possible directly in add_column. The common approach would be:

    • create a nullable column;
    • fill it with generated uids;
    • update the column definition.

    In your code, proc { generate_unique_id }.call makes not much sense, since it is an absolute equavalent of generate_unique_id.

     add_column :users, :unique_id, :string, null: true
     # it’s still a plain ruby code!
     User.find_each do |u|
       # or better use built-in SQL functoin to do this in batch
       #    inside your db, instead of performing a dozillion of updates
       u.update_column(:unique_id, generate_unique_id)
     end
     change_column :users, :unique_id, :string, null: false # NOW!