aasm を 4.10.0 にあげると Job: overriding method 'sleeping?'! のような警告が出るようになってしまい、Warning when specifing states at ActiveRecord enum で報告されているものの、まだ何も対応されていないので、とりあえず monkey patch で対処することにしました。

対象バージョン

  • ruby 2.2.4
  • rails 4.2.6
  • aasm 4.10.0

対処方針

モデルごとに対応するのは面倒なことになるので、 Rails 5 で導入される予定の ApplicationRecord に対応して、そこに対処を入れることにしました。

ApplicationRecord 対応

まず sed -i~ -e 's/ActiveRecord::Base/ApplicationRecord/' app/models/*.rb などで継承元を ActiveRecord::Base から ApplicationRecord に書き換えます。 (実際には application_record.rb の作成後にやってしまって RuntimeError: Circular dependency detected while autoloading constant ApplicationRecord になってしまったので、 application_record.rb だけ元に戻しました。)

次に以下の内容で app/models/application_record.rb を作成します。

app/models/application_record.rb:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

テスト実行などで影響がないことを確認します。

monkey patch

aasm の README に書いてあるように

app/models/job.rb:

class Job < ApplicationRecord
  include AASM

  enum state: {
    sleeping: 5,
    running: 99
  }

  aasm :column => :state, :enum => true do
    state :sleeping, :initial => true
    state :running
  end
end

のようなハッシュを使った enum 呼び出ししかしていなかった (enum status: [ :active, :archived ] のような配列を使った呼び出しはしていなかった) ので、以下のように each_valueeach_key の組み合わせ決め打ちで undef_method を呼び出すことにしました。

app/models/application_record.rb:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  if AASM::VERSION == '4.10.0'
    def self.enum(definitions)
      super
      definitions.each_value do |statuses|
        statuses.each_key do |key|
          undef_method "#{key}?"
        end
      end
    end
  end
end

ActiveRecord::Enum では enum を呼び出したクラスに直接 sleeping? などのメソッドを定義するのではなく、無名モジュールに定義されているので、 remove_method ではなく undef_method を使う必要がありました。 (aasmaasm を呼び出したクラスに直接定義していました。)

今後の予定

将来のバージョンでどう挙動が変わるのかわからないので、バージョン番号決め打ちで monkey patch をあてていて、バージョンアップで問題が再発するようならバージョン番号を更新、解決するようなら monkey patch を削除しようと思っています。

Disqus Comments

Kazuhiro NISHIYAMA

Ruby のコミッターとかやってます。 フルスタックエンジニア(って何?)かもしれません。 About znzに主なアカウントをまとめました。

znz znz


Published