この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
Railsのgeneratorでmigrationが二つ以上ある時の対策をしました。
Railsのgenerator対応のプラグインを作成している時に、migrationが二つ以上あるとdb:migrateに失敗してしまいます。
エラーの内容は以下のとおりです(一部伏せています)。
bash-3.2$ script/generate xxx_payment -f XxxPayment
exists app/models/
exists config/initializers/
exists spec/controllers/
exists spec/factories/
force app/models/xxx_payment_plugin.rb
create app/models/xxx_payment_results.rb
identical config/initializers/xxx_payment_cart_controller_extend.rb
force spec/controllers/xxx_cart_controller_spec.rb
force spec/factories/xxx_payments.rb
exists db/migrate
create db/migrate/20100831124224_create_xxx_payment_plugins.rb
exists db/migrate
create db/migrate/20100831124224_create_xxx_payment_results.rb
bash-3.2$ rake db:migrate
(in /Users/btm/develop/elecoma/devel_git)rake aborted!
Multiple migrations have the version number 20100831124224
(See full trace by running task with --trace)
このように二つのmigrationが同じ日付になっているため、「Multiple migrations have the version number」となってしまうのです。
では、対策をしてみましょう。実際のところ、時間の取り出しはnext_migration_stringというメソッドで行われているようです。
# rails-2.3.5/lib/rails_generator/commands.rb
def next_migration_string(padding = 3)
if ActiveRecord::Base.timestamped_migrations
Time.now.utc.strftime("%Y%m%d%H%M%S")
else
"%.#{padding}d" % next_migration_number
end
end
結局のところ、Time.nowのタイミングをずらせばよいというのがわかります。
なので、generatorでは以下のように書けばOKです。
# xxx_payment_generator.rb
class XxxPaymentGenerator < Rails::Generator::NamedBase
default_options :skip_migration => false
...
def manifest
record do |m|
...
# migration
# migration
unless options[:skip_migration]
m.migration_template 'create_xxx_payment_plugins.rb',
'db/migrate',
:assigns => {},
:migration_file_name => "create_xxx_payment_plugins"
m.sleep 1
m.migration_template 'create_xxx_payment_results.rb',
'db/migrate',
:assigns => {},
:migration_file_name => "create_xxx_payment_results"
end
...
end
end
end
m.migration_template 同士の間に “m.sleep 1 “として一秒間ずらしてあげます。
では、作成してみましょう。
bash-3.2$ script/generate xxx_payment -f XxxPayment
exists app/models/
exists config/initializers/
exists spec/controllers/
exists spec/factories/
identical app/models/xxx_payment_plugin.rb
identical app/models/xxx_payment_results.rb
identical config/initializers/xxx_payment_cart_controller_extend.rb
identical spec/controllers/xxx_cart_controller_spec.rb
identical spec/factories/xxx_payments.rb
exists db/migrate
create db/migrate/20100831131456_create_xxx_payment_plugins.rb
exists db/migrate
create db/migrate/20100831131457_create_xxx_payment_results.rb
Versionが一つずれて作成されているのがわかります。これで、無事マイグレートができるようになりました。
同じエラーではまった人は参考にしていただけると幸いです。