I'm pushing for adoption of Rails Migration on all Rails projects on my job (we use them on a few). As a consequence, I won the assignment of writing migrations for the last changes on the system I'm currently involved. That seemed easy, but it wasn't. I will try to show why, without diving into details of my specific scenario.
Imagine you have the following model:
class Foo < ActiveRecord::Base end
And the following migration:
class AddAnotherFieldToFoo < ActiveRecord::Migration def self.up add_column :foo, :new_column, :string Foo.reset_column_information Foo.find(:all).each do |foo| foo.new_column = some_calculation(foo.another_column) foo.save! end end end
Now, we make the following changes to our model:
class Foo < ActiveRecord::Base **has_many :bars** **before_save :do_something_with_my_bars** **def do_something_with_my_bars** ** ...** **end** end
And its migration (just for completeness, not really relevant):
class AddBazToFoo < ActiveRecord::Migration def self.up add_column :foo, :bar_id, :integer end end
So what is the problem?
For us, who made the last change on Foo after doing the AddAnotherFieldToFoo migration, it's all fine.
But, for the new developer who just made a checkout of the source code and happily executed rake db:migrate, the AddAnotherFieldToFoo migration failed miserably.
That's because Foo#dosomethingwith_bars will get called (remember the
:before_save we introduced), but the association between foo and bar is not made yet (we are executing a previous migration).
Same happens to the developer who didn't update his local copy this week. And it will break on production too, when we merge this set of changes into the production branch.
So, here is my problem:
Every backward incompatible change to models will (potentially) break past migrations, because they are not specifically associated to a model state on the time. And SCMs doesn't help either (updating one changeset at time would work, but when merging braches all that changesets will collapse into one and you are doomed) I'm looking into what to do. Maybe I'm using migrations in a way they were not intended to be used...
Does someone know how to solve this?
Update: Here is the ruby-talk thread