Yeah,
The whole point of migrations is that they are cumulative. Each
migration builds on the previous one(s). So, in essence, you could
recreate everything (other than data, usually) by dropping the DB,
then remigrating through all of them. And the self.up and self.down is
simply to make sure that whatever you “do” in one migration, you
“undo” in the self.down, so you can move up or down the migration
tree.
Think of it as a series of transformations and anti-transformations.
If I have 10 migrations, I should be able to migrate back to #6 (rake
db:migrate VERSION=6) then pop up to 8 (rake db:migrate VERSION=8) and
whatever else.
Some other thoughts from one whose done quite a few Rails projects:
- if it’s only you, it’s less important. Migrations matter a lot more
on shared projects. In fact, I’ve seen some patches that suggest that
future versions of Rails will include migration modifications to make
name collisions less likely.
For my part, on projects that I’m the only developer, I only use
migrations in a post-launch state. Up until then, I’ll still use
migrations temporarily as I generate new models/scaffolds/controllers/
etc., but then I “flatten” them back into the original 001. So that is
my only migration and effectively is the “current state” of the app’s
schema. I do this by hand… although you could simply copy schema.db
into your 001 migration as it’s effectively the same thing.
I also built some custom rake tasks to make my life easier. For
example, I have “rake db:remigrate” which does the drop table, create
table and migrate all in one… saves some typing. And I have a “rake
data:load” which cranks through a bootstrap file and loads a bunch of
data. I used to just use the fixture data, but I prefer a bootstrap
option because it’s just a normal Ruby class (with all the Rails
environment, though) and I can do console-like calls. (I know there
are options to incorporate this into fixtures, but I decided not to go
that route).
- Once you’ve “launched”, it’s a different world. From that point on,
you can’t (or rather… “really don’t want to”) roll back migrations.
If you launched with only a 001 migration, that one becomes
sacrosanct. So any changes start with 002. Then, I usually do the same
thing, but 002 is the “baseline”. I.e. I “flatten” my migrations down
to 002 until the changes are pushed live. Then 002 becomes the new
baseline. Etc. Again, this only works if you are the only one one
developing… or if you work closely and carefully with the rest of
the team.
Craig: one thing: I found this lovely little snippit that I use:
def self.down
drop_created_tables
end
def self.drop_created_tables
File.read(__FILE__).scan(/create_table :(\w+)/).each { |table|
drop_table table[0].to_sym }
end
The beauty there is that I don’t have to remember to keep the
“self.down” method in sync with the “self.up”. If I were using
multiple migrations with lots of add_columns and the like, this
wouldn’t work, but with my “flatten” method of working, it’s nice. My
001 migration is pretty huge on some large projects, but still easy to
navigate through.
-Danimal
On May 18, 2:41 pm, “Craig D.” [email protected]