Guys, I've run across an interesting scenario with my migrations, and I hope you might share some insight. Let's say I have 3 migrations and two Models (Person and Car): 001_initial_schema.rb 002_data_load.rb 003_add_car_association.rb The first creates the initial schema...the second loads default data using model objects of Person to do so, and the third creates a new table, "cars", and modifies the "persons" table to create a :has_one relationship of Person->Car. Let's also say I want all Persons to have at least one car, so I change my Person model to have: def after_initialize self.car = Car.new unless self.car end Now, what happens, is that when I issue a "rake migrate" on my intial database When I start from scratch (new database) and do a rake migrate, my data load fails because it uses the model class Person, yet Person's code now has an after_initialize that expects the Car association to be present. Because Car isn't created until migration 003, I'm essentially up the creek. rake throwns an InvalidStatement exception. Has anyone found a decent way of handling these scenarios? Thanks! John
on 2006-02-24 19:17
on 2006-02-24 19:38
> Thanks! > John I prefer to keep my migrations free of my models for this very reason. I'll create temp models if I need to do basic queries, however. class MyMigration < Migration class Article < AR::Base end def self.up end def self.down end end This essentially makes the model's name MyMigration::Article, and won't clash with your app's Article model or any other migrations' Article models. disclaimer: I haven't *actually* tried this. However, I ran into this issue on my Mephisto blogging tool and created temp models like TempArticle. Someone had a question on the Rails-Core ML and led me to this idea. I'll try it next. http://techno-weenie.net/svn/projects/mephisto/tru... -- Rick Olson http://techno-weenie.net
on 2006-02-24 19:39
> I've run across an interesting scenario with my migrations, and I hope > you might share some insight. > ... > Has anyone found a decent way of handling these scenarios? http://scottstuff.net/blog/articles/2005/10/31/mig... http://rails.techno-weenie.net/tip/2006/2/23/safel...
on 2006-02-25 11:42
Rick Olson wrote: > def self.down > end > end > > This essentially makes the model's name MyMigration::Article, and > won't clash with your app's Article model or any other migrations' > Article models. > > disclaimer: I haven't *actually* tried this. Having googled a bit, and seen your conversation on the rails-core list, I did try it. It works. Very nicely :-) It's a situation that I'm surprised doesn't come up more often. Changes to models breaking old migrations must be quite a common occurrence, both because of lifecycle callbacks and because of relationship changes. The rules of thumb I've come up with are: - Always use local models in migrations (as above). An alternative would be a patch to AR that exposed create_without_callbacks, but that was more complex than I wanted to get in to, and wouldn't cover everything. - Never rely on dynamic associations, always use foo[:bar_id] = qux[:id] rather than foo.bar = qux. I've found that following those rules allows changes to model code while also letting your app bootstrap itself in a single rake migrate pass.