I changed my mind about this since I sent my last response: I think doing anything outside of modifying the database (*seeding is pushing it, but I think in some cases it is acceptable*) is definitely a hack.
Reflecting on the history of Rails, particularly what led to the addition of seed.rb and the rake db:seed - I realized even seeding the database in migrations is a bad idea in all cases - unless the migrations DSL provides a way to do that and have that reflected in schema.rb/sql, which I don't believe is possible. I think, the rule of thumb is that if you are doing anything in your migrations that would case your schema.rb/sql + seed.rb to be out of sync with your actual database state (i.e. running db:schema:load and db:seed is not sufficient to boot a fresh instance of your app), then you are doing it wrong. The best way to do seeding is to make sure your seed.rb is "one-way idempotent" (as in - running db:seed multiple times on incremental rollbacks would not create duplicate data, etc. Use find_or_create_by and friends to help) and run that after every deploy together with db:migrate. Of course, when it comes to rolling back a deploy, you'd still have to figure out what to do with those data on a case-by-case basis, but that's expected for any non-idempotent actions you perform on deploy. Alternatively, if you engineered a custom framework/workflow for these after deploy actions (deploy-specific cap scripts and whatnot), then you could do the seeding there, but you'd still want to keep your seed.rb up to date. On Mon, Feb 18, 2013 at 4:27 AM, Godfrey Chan <[email protected]> wrote: > @mrloz > > I think doing anything outside of modifying the database (seeding is > pushing it, but I think in some cases it is acceptable) is definitely a > hack. The immediately obvious problem with that solution is that some of > the tasks you described is not idempotent, such as sending emails. This > might case problem if you experienced problems with your new deploy and had > to roll back the changes temporarily and revert the rollback at a later > time. You can raise an exception on rollback, but since you'll have to > determine how to manually recover from the broken state (and how to restore > it later), I don't quite see what you are gaining here. > > Deployment is one of the few things that Rails doesn't manage for you > since it is difficult to come up with a general framework that is a good > enough starting point for most people. Migrations is designed specifically > to manage changes to your database schema, and is not technically tied your > deployment flow (while you might just automatically run db:migrate on every > deploy, it is not exactly straight forward to keep your schema in sync with > your code on rollback). > > So, because Rails doesn't dictate how you manage your deployment workflow, > you'd just have to engineer your own solution that works for your > particular deployment flow. > > @rodrigo > > Even if you just modify schemas, the only reliable way I know of > recreating your db is to run all migrations. > > ... > > This doesn't work for many cases if your schema format is :ruby (the > default). > > ... > > Unless you use :sql for schema_format of course. > > > I think you kind of had it backwards: > > 1. The purpose of schema.rb/sql is exactly what the guides described - to > recreate the database schema on a new instance of the app without having to > re-run all the migrations. > > 2. You are correct that schema_format = :ruby does not support > vendor-specific features like HStores or other "advanced" SQL features like > foreign key constraints. > > From 1 & 2, the obvious conclusion should be that "If you are using any > vendor-specific or advanced SQL features, you should turn on schema_format > = :sql" instead of "If you are using any vendor-specific or advanced SQL > features, you should re-run all your migrations on a fresh deploy." > > As for the foreign-key constraints debate, IIRC it was quite controversial > in the early days of Rails, but it's a largely settled debate. There are > still different opinions on this of course, but at the end of the day Rails > would have to pick a default convention, and "intelligence belongs in > your models" have won. And hence schema_format = :ruby is the default. > (With new AR features like hstore support on the horizon, that decision > might worth a revisit, but that'd be a separate discussion.) > > You can still choose to use vendor-specific or advanced SQL features of > course, hence the ability to toggle that setting to :sql. > > Godfrey > -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
