ホーム DoRuby RailsのgeneratorでMultiple migrationsとなる件の対応方法

RailsのgeneratorでMultiple migrationsとなる件の対応方法

この記事はアピリッツの技術ブログ「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が一つずれて作成されているのがわかります。これで、無事マイグレートができるようになりました。

同じエラーではまった人は参考にしていただけると幸いです。

記事を共有

最近人気な記事