On Jan 17, 4:14 pm, Yorick Peterse <[email protected]> wrote:
> Currently I'm working on a CMS that allows developers to create and install
> third-party extensions. These extensions can contain controllers, models,
> helpers, the whole shebang.
> In order to make the installation/development process easier migrations are
> used for each extension. The basic structure of each extension is the same
> as your average gem:
>
> extensions
> |
> |__ my_extension
> |
> |__ lib
> | |
> | |__ my_extension
> | |__ my_extension.rb
> |
> |__ migrations
> |
> |__ 1234567890_create_schema.rb
>
> As you can see, nothing really special. There is however one big problem
> when using Sequel migrations. By default Sequel uses a single column to keep
> track of the last run migration.
> While this is no problem for a single directory this can cause problems
> pretty quickly when running migrations from multiple directories (with the
> possibility of the same name being used N times).
> To solve this problem I figured that it would be best to give each extension
> it's own column. When installed this column would be created, the initial
> migrations would be executed and you're good to go.
> Well, turns out it's not that easy. The problem is that Sequel expects the
> column to be there once the table is created, which makes sense and can be
> solved quite easily. The bigger problem however
> is that it seems to expect that at least 1 migration was executed before
> creating the column, creating the column and not running any migration
> (regardless of the column value) will trigger an error like
> the following:
>
> Applied migration files not in file system: 20000101_test.rb
>
> Whether the column value is NULL, 0, "" or "cookies" Sequel will never run
> the migration UNLESS the column value matches an existing migration. This is
> fine...when you've actually ran any migrations.
> When running an installation for the first time however Sequel will bail out
> and the migration is never executed. The code I'm using to install
> extensions is the following:http://scrp.at/pvNote that this Rake
> task will work fine for the first migration executed (as no columns exist
> yet) but any following migrations won't be executed.
>
> So the question is, how to get around this. Personally I think this issue
> could be solved by 1. finding out if Sequel requires some sort of default
> value 2. Modifying Sequel itself to do the same process for N columns
> rather than only the first one. The latter most likely produces the best
> results but this will also cause the issue of possibly ending up with N
> columns if you happen to have a few typos/errors in your code.
>
> To make it a bit easier to understand I've listed the installation steps of
> an extension below:
>
> 1. install the actual application
> 2. download an extension (either using Rubygems or something else)
> 3. require it in a config file (config/requires.rb)
> 4. run "rake extension:install["com.some-extension.identifier"]". This runs
> the migration(s) for the extension
> 5. done
>
> Here's a screenshot that shows a basic example of the installation
> process:http://grab.by/8r0t
> As you can see the initial installation works fine as there's no
> "schema_migrations" table yet, the second migration however fails as the
> column is there (created by the Rake task) but has no value. Sequel thinks
> this is a migration, tries to execute/find it and fails as the file ""/NULL
> doesn't exist.
>
> Free E-beer for the one who can help me out!
My personal feeling is that any schema modification files should be
copied to your main schema directory, since they affect the same
database. I'd only use separate directories if the migrations were
for different databases. That's not to say you shouldn't distribute
the schema files with your extension, but if you copy them to the main
schema directory first, you avoid this problem.
With the current code, instead of using a different column in the same
table, if you use a different table (schema_migrations_foo), you avoid
the problem as well.
There's not going to be a way to get multiple separate columns to work
with the TimestampMigrator with the current code. You could use the
patch below, which will skip entries with NULL values, but I don't
think it's a good idea for Sequel to do so in general, as it's more
likely to hide problems than solve them in the average app. If you
think about how the TimestampMigrator would have to store multiple
independent migration directories in the same table, I think you'd
agree with me.
I strongly urge you to either copy the files to the main schema
directory, and if you can't do that, use a different table for the
migrations for your extensions.
Jeremy
diff --git a/lib/sequel/extensions/migration.rb b/lib/sequel/
extensions/migration.rb
index 239b2b3..ca516ba 100644
--- a/lib/sequel/extensions/migration.rb
+++ b/lib/sequel/extensions/migration.rb
@@ -575,7 +575,7 @@ module Sequel
# Returns filenames of all applied migrations
def get_applied_migrations
- am = ds.select_order_map(column)
+ am = ds.exclude(column=>nil).select_order_map(column)
missing_migration_files = am - files.map{|f|
File.basename(f).downcase}
raise(Error, "Applied migration files not in file system:
#{missing_migration_files.join(', ')}") if
missing_migration_files.length > 0
am
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sequel-talk?hl=en.