2012-03-16

rails3で、あるactionに対してrouteがマッチしないケースがあった

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
複数のコントローラーで共通で使いたいactionがあるので、以下のようなcontrollerを作成して継承して使ってみていました。

class AaaController < ApplicationController
  def load
    ...
  end
  def loading
    ...
  end
end


実際に使う際は、こんな感じです。

class BbbController < AaaController
  def bbb
    ...
  end
end


rails 2.3の時は、なんの問題もなかったのですが、
rails 3.0にしてみたらBbbControllerでloadアクションが見つからなくなってしまいました。

ためしに、BbbControllerを以下のように変更したら、ちゃんと動くので気持ち悪い状態です。

class BbbController < AaaController
  def load
    super
  end
  def bbb
    ...
  end
end


rails c
で確認してみたところ、確かにloadメソッドはBbbControllerでも認識されているのに、actionとしては認識されていない状況でした。
irb(main):> c1 = AaaController.new
irb(main):> c2 = BbbController.new
irb(main):> c1.method(:load)
=> #<Method: AaaController#load>
irb(main):> c2.method(:load)
=> #<Method: BbbController(AaaController)#load>
irb(main):> c1.action_methods
=> #<Set: {"load","loading"}>
irb(main):> c2.action_methods
=> #<Set: {"loading"}>


一度AaaControllerからloadアクションを削除してみて確認したところ、Railsのどっかでloadメソッドが定義されていたことがわかりました。
irb(main):> c2 = BbbController.new
irb(main):> c2.method(:load)
=> #<Method: BbbController(ActiveSupport::Dependencies::Loadable)#load>

Railsのソースを見てみたところ、Controller内で定義されているものは、きちんとactionとして認識されるのですが、継承したmethodに関しては、すべてがactionと認識されるわけではなく、Railsのどっかで定義しているmethodに関してはactionにならないことがわかりました。

なのでloadが使えない対策は、loadの名称変更になりました。

共通のactionを使いたいということであれば、クラスを敬称させるのでなくてモジュールにしてincludeした方がよかったかなぁとか思ったりもしてみました。


コメントを投稿