Hi Sven,
Thanks for taking the time to read my article and write your
response
I've read your blog post but I don't quite get a few problems that you
point at.
In solution #1 you say that "Next to run is the application's
migration, creating a users table, which should not exist. Failure."
What's the failure here? The users table won't exist before
20080101_create_users (as long as 20071201_create_accounts does not
mess with the users table, which it shouldn't). If I don't get you
wrong we've been using a similar approach for a while and it worked
well for this scenario.
The issue, although I'll grant that my simple example doesn't
illustrate it well, is that the migrations are being applied in the
wrong order. I'll leave it up to everyone else to either flesh out a
better example, or declare the migration order is not important. I
hope that the article, as a whole, is successful at describing *why* I
believe that migration order is significant.
If not, see the example below, where an app and a plugin are dealing
with tables with the same name, instead of 'users' vs. 'accounts'.
In solution #2 the misconception imho is that the app migrations are
run first and the plugin migrations run afterwards. That of course
won't work when the app wants to modify what plugins provided.
Traditionally plugins were more seen as part of the framework/
libraries, today they also might be parallel slices of an application.
In both cases the order "app first, plugins second" seems wrong to me.
If anything app migrations would need to run after plugin migrations.
Or the timelines need to be mixed.
Here, you might be suggesting that plugin migrations should run first
(which is, I think, also what Luca's latest patch does). I don't think
this could ever work well enough to be described as a 'feature'.
Consider an example where the app has its own 'users' table, then the
developer replaces it with one from a plugin by creating an app
migration to remove his existing table, and then running the plugin
migration. Running the migrations from scratch using the above
strategy would result in two attempts to create the 'users' table (the
first from the plugin, the second from the app), which will at best
fail, and at worse silently drop the existing table.
If instead you believe that the timelines need to be mixed, I think
you'll end up with one of two solutions - either copying/
retimestamping migrations, or creating intermediate migrations in the
app timeline.
For the "rollback problem", i.e. rolling back all migrations from a
plugin: even if plugin migration timestamps are not tracked
explicitely one can always inspect the plugin migrations directory. So
for uninstalling/rolling back a plugin a dedicated rake task could
work that looks at the plugin migrations folder and migrates the
plugin down.
Yes, this is possible, and something that I spoke about a little bit
with Yehuda Katz at Scotland on Rails last week. However, I can't see
the sense in creating specific code to quite literally tear out some
tables from the database, when I believe a general mechanism is
possible without creating any conceptual overhead.
This obviously would clash when the app messed with the
plugin's tables and one would need to migrate the app migrations down
manually ... which imo seems ok though.
I'm not sure how this can be OK. In order for migrations to be a
viable mechanism, I need to be able to trust them with my production
database. If I know there's even some chance (outside of the mistakes
I make myself) that I might be forced to unpick migrations manually on
production data, I no longer feel so great about trusting any
migrations from plugins at all.
Clearly this is a big problem, conceptually at least*.
Even if we don't make any more progress here, at some point we're
going to have to produce some 'best practice' advice for people
wanting to provide migrations in their plugins, and without any
direction from the framework, that best advice is going to be
something along the lines of "use a generator"** or "copy them as part
of install.rb".
I'm not sure how best to proceed. Perhaps I should look at the
'copying stylesheets/javascripts' aspect of engines instead!
James
* It gets even bigger/weirder with Rails 3, where there's no way for a
plugin to predict the ORM used by the app.
** I'll leave exploring the pitfalls of this up to the reader.