У меня есть структура папок, которая выглядит следующим образом:
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
баз.рб
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
Итак, я предполагаю, что создал какую-то циклическую зависимость, определяющую константу с объектами класса. Кто-нибудь может подтвердить? Странно, что он просто молча терпит неудачу, не определяя методы класса в классе, к которому обращаются вторым. Я не знаю, почему это?
Foo::Bar
иFoo::Baz
фактически расширяют другой базовый класс, который открывает соединение со сторонней базой данных, как описано здесь: ilikestuffblog.com/2012/09/21/ Но этот базовый класс не включает миксин и не делает ничего особенного, кроме подключения к внешней базе данных. - person Gray Kemmey   schedule 11.12.2015