次のようなフォルダー構造があります。
app/models/
concerns/
quxable.rb
foo/
bar.rb
baz.rb
私はRails 3にいるので、懸念事項を次のものでオートロードしました:
config.autoload_paths += Dir[Rails.root.join('app', 'models', "concerns", '**/')]
そして、ファイルは次のとおりです。
quxable.rb
module Quxable
extend ActiveSupport::Concern
module ClassMethods
def new_method
end
end
end
bar.rb
class Foo::Bar < ActiveRecord::Base
include Quxable
end
baz.rb
class Foo::Baz < ActiveRecord::Base
include Quxable
end
コンソールでこれを行うと、次の出力が得られます。
Foo::Bar.respond_to? :new_method #=> true
Foo::Baz.respond_to? :new_method #=> false
reload!
Foo::Baz.respond_to? :new_method #=> true
Foo::Bar.respond_to? :new_method #=> false
そのため、最初にアクセスしたモデルにのみ適切に含まれているように見えます。それでも、次を実行すると:
ActiveRecord::Base.descendants.select{ |c| c.included_modules.include?(Quxable) }.map(&:name)
私は得る["Foo::Bar", "Foo::Baz"]
。
ここで何が起こっているのか分かりますか?オートローディング/イーガーローディングで何かを推測していますが、両方のモデルが新しいクラス メソッドを取得していない理由がわかりません。
PS - 以下を使用せずにモジュールを書き直そうとしましたActiveSupport::Concern
(Rails の古いバージョンを使用していて、暗がりで撮影しているという理由だけで):
def include(base)
base.send :extend, ClassMethods
end
しかし、私はまだ同じ問題を抱えています。
編集
最初はこれを省略しました (最も単純な問題を提示しようとしているだけです)。しかし、quxable.rb
実際には次のようになります。
module Quxable
extend ActiveSupport::Concern
LOOKUP = {
Foo::Bar => "something",
Foo::Baz => "something else"
}
module ClassMethods
def new_method
end
end
end
だから私は Class オブジェクトで定数を定義するある種の循環依存関係を作成したと推測しています。誰でも確認できますか?ただし、2番目にアクセスされるクラスのクラスメソッドを定義しないことで、サイレントに失敗するのは奇妙です。なぜだかわかりませんか?