Search code examples
ruby-on-railsrubydata-migrationrails-migrations

Migrating DATA - not just schema, Rails


Sometimes, data migrations are required. As time passes, code changes and migrations using your domain model are no longer valid and migrations fail. What are the best practices for migrating data?

I tried make an example to clarify the problem:

Consider this. You have a migration

class ChangeFromPartnerAppliedToAppliedAt < ActiveRecord::Migration
  def up
    User.all.each do |user|
      user.applied_at = user.partner_application_at
      user.save
   end
 end

this runs perfectly fine, of course. Later, you need a schema change

class AddAcceptanceConfirmedAt < ActiveRecord::Migration
  def change
    add_column :users, :acceptance_confirmed_at, :datetime
  end
end

class User < ActiveRecord::Base
  before_save :do_something_with_acceptance_confirmed_at
end

For you, no problem. It runs perfectly. But if your coworker pulls both these today, not having run the first migration yet, he'll get this error on running the first migration:

rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `acceptance_confirmed_at=' for #<User:0x007f85902346d8>

That's not being a team player, he'll be fixing the bug you introduced. What should you have done?


Solution

  • Best practice is: don't use models in migrations. Migrations change the way AR maps, so do not use them at all. Do it all with SQL. This way it will always work.

    This:

    User.all.each do |user|
      user.applied_at = user.partner_application_at
      user.save
    end
    

    I would do like this

    update "UPDATE users SET applied_at=partner_application_at"