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[1]->[1]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 -- Posted with http://DevLists.com. Sign up and save your time!
> 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! > JohnI 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/trunk/db/migrate/ -- Rick Olson http://techno-weenie.net
Joshua Susser
2006-Feb-24 18:39 UTC
[Rails] Re: Migrations, data loads and changes to the model
> 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/migrating-in-two-dimensions http://rails.techno-weenie.net/tip/2006/2/23/safely_using_models_in_migrations -- Posted via http://www.ruby-forum.com/.
Rick Olson wrote:> 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.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. -- Alex