Why is AR migrations using one file per migration?

Hi, I’m currently in the process of rethinking some of the design decisions I’ve taken in my first attempt to add migrations support to Lobos, a Clojure schema manipulation library. I’ve based this work mostly on ActiveRecord, but now that I’m getting some feedback on it, I really wonder why Rails migrations are spread around into individual files. Wouldn’t it be better to simply add the timestamp to the migrations name and put them all into one file?

Here’s the discussion that made me ask this question:

https://groups.google.com/d/topic/lobos-library/GnFBKahrhY0/discussion

Wouldn’t it be better to simply add the timestamp to the migrations name and put them all into one file?

Not really. Consider this simple scenario for one example of why it’s a bad idea to have them in the same file.

I check out the source code to our application and add a migration.

You check out the source code to our application and add a different migration.

If they are in the same file, we have a conflict when it’s time to check in our code.

If they are in separate files, there won’t be any conflict when we both check in our code.

Hi, I'm currently in the process of rethinking some of the design decisions
I've taken in my first attempt to add migrations support to Lobos, a Clojure
schema manipulation library. I've based this work mostly on ActiveRecord,
but now that I'm getting some feedback on it, I really wonder why Rails
migrations are spread around into individual files. Wouldn't it be better to
simply add the timestamp to the migrations name and put them all into one
file?

Just off the top of my head, it is probably easier to write a
generator that creates a new migration file than one that edits an
existing file

Fred

Yes, that’s about the worse drawback I had thought about, but this issue
is quite moot. One dev will only have to do a proper merge and that’s it.

Yes, that’s about the worse drawback I had thought about, but this issue
is quite moot. One dev will only have to do a proper merge and that’s it.

Right. It is actually a really good question you raise, and yes a merge would not be any different than two devs who have modified any other file, git handles that gracefully. One thing I thoght of that at first I thought would make a one file situation more difficult but on reflection make a one file situation easier is rolling up migrations — once I accumulate a lot of migrations I roll them up and dump the contents of the schema into the initial migration. Having one file would allow me just to delete text and copy rather than having to delete files. Not a big deal but one less step.

Yes, that would be a nice advantage. For Lobos, this could go one step further, as Clojure evaluates source code linearly, I could make the migrations ordered by their position into the file, thus making it really easy to reorder migrations.

Right. It is actually a really good question you raise, and yes a merge would not be any different than two devs who have modified any other file, git handles that gracefully. One thing I thoght of that at first I thought would make a one file situation more difficult but on reflection make a one file situation easier is rolling up migrations — once I accumulate a lot of migrations I roll them up and dump the contents of the schema into the initial migration. Having one file would allow me just to delete text and copy rather than having to delete files. Not a big deal but one less step.

Yes, that would be a nice advantage. For Lobos, this could go one step further, as Clojure evaluates source code linearly, I could make the migrations ordered by their position into the file, thus making it really easy to reorder migrations.

Hmm. but how would that work if you have dependencies? Like if you move a migration which adds a field to a table before you create the table? What would be cool is that you could order the file in any order by Rails would run the migrations in sequence regardless of the order in the file (I am assuming each ‘migration’ in the file would have some sort of id or timestamp). Thinking more, one more advantage is that it would be easier to find changes say for a specific table. Right now I just have to grep for it unless I can read the five mile long name I have given the file.

Right. It is actually a really good question you raise, and yes a merge would not be any different than two devs who have modified any other file, git handles that gracefully. One thing I thoght of that at first I thought would make a one file situation more difficult but on reflection make a one file situation easier is rolling up migrations — once I accumulate a lot of migrations I roll them up and dump the contents of the schema into the initial migration. Having one file would allow me just to delete text and copy rather than having to delete files. Not a big deal but one less step.

Yes, that would be a nice advantage. For Lobos, this could go one step further, as Clojure evaluates source code linearly, I could make the migrations ordered by their position into the file, thus making it really easy to reorder migrations.

Hmm. but how would that work if you have dependencies? Like if you move a migration which adds a field to a table before you create the table?

That would be the responsibility of the developer for now. I could make my library analyze the migrations to find such conflicts, that might be a feature to add in some future release, but I’m not sure it’s worth it.

What would be cool is that you could order the file in any order by Rails would run the migrations in sequence regardless of the order in the file (I am assuming each ‘migration’ in the file would have some sort of id or timestamp).

Unless I’m mistaken, that would be the only way to implement the ‘all migrations into one file’ feature in Ruby, at least without resorting to top-level calls ensuring the order of evaluation. Although I must say that I’m not that good at Ruby meta-programming.

Thinking more, one more advantage is that it would be easier to find changes say for a specific table. Right now I just have to grep for it unless I can read the five mile long name I have given the file.

Yeah, while thinking about this, I realized how tiring it can be to search/consult/erase migrations files and I’m more and more sold to put all migrations into one file.

Why go half-way? Put all the models in one file too, bundle all the
controllers in with them, and you can whip the helpers in at the
bottom (we don't need them often)

Alternatively, there's no serious issue at all with having migrations
in separate files - yes, in one file I *can* merge them in my source
control software, but if they're in their own files I don't have to
bother. For the zero benefit that one migration file over lots of
files gives me, I can avoid the extra niggle of having to resolve
merge conflicts in it.

:-/

PS What do you ever search migrations for? Everything I've ever needed
is in schema.rb, or I just look in the DB...

Yeah, while thinking about this, I realized how tiring it can be to

search/consult/erase migrations files and I’m more and more sold to put all

migrations into one file.

Why go half-way? Put all the models in one file too, bundle all the

controllers in with them, and you can whip the helpers in at the

bottom (we don’t need them often)

hahaa, I get it but if you want to make the analogy exact, it would be to change rails so every time a model is changed it creates a new file that extends the model. And then we would have the generator which puts everything into one big file, like the schema :slight_smile:

Yeah, while thinking about this, I realized how tiring it can be to
search/consult/erase migrations files and I’m more and more sold to put all
migrations into one file.
Why go half-way? Put all the models in one file too, bundle all the
controllers in with them, and you can whip the helpers in at the
bottom (we don’t need them often)

Lol, good one, but more seriously, the problem with migrations is just that the timestamps comes first making annoying to open in Emacs. That’s a very personal issue though, as I never got used to things like ido-mode.

Alternatively, there’s no serious issue at all with having migrations
in separate files - yes, in one file I can merge them in my source
control software, but if they’re in their own files I don’t have to
bother. For the zero benefit that one migration file over lots of
files gives me, I can avoid the extra niggle of having to resolve
merge conflicts in it.

I understand and I’m not condemning AR on that design decision, which is perfectly fine. I’m just trying to see if there’s some issue I’m overlooking by putting all migrations into one file, which could have more concrete advantages in the library I’m writing.

PS What do you ever search migrations for? Everything I’ve ever needed
is in schema.rb, or I just look in the DB…

Searching migrations is not something I’m doing often, but it could help sometimes to investigate why something have been done in a certain way.