Вот что я в итоге сделал:
(1) В классе app/lib/foo.rb
я добавил статический метод, требующий соответствующие файлы
def self.load_foos
Dir["#{Rails.root}/app/lib/foos/*_foo.rb"].each do |file|
require file
end
end
(2) вfoo.rb
, я добавил статический метод, чтобы подклассы могли регистрировать себя
def self.register
if @@subclasses.include?( self.registration_symbol )
raise FooExceptionSymbolAlreadyUsed, "symbol [#{self.registration_symbol}] is already in use."
end
@@subclasses[self.registration_symbol] = [self.registration_priority,self]
end
(3) Я создал каталог на app/lib/foos
, где я поместил различные подклассы foo и назвал их this_foo.rb
и that_foo.rb
.
(4) В подкласс app/lib/foos/this_foo.rb
я добавил следующее
class Foos::ThisFoo < Foo
def self.registration_symbol
:this
end
def self.registration_priority
100
end
# other methods removed to make example easier to read
register
end
(5) Я добавил config/initializers/load_foos.rb
, который просто имел
Foo::load_foos
Любой подкласс Foo, который я вставил в app/lib/foos/
и правильно назвал, будет автоматически загружаться при запуске.Каждый подкласс переопределяет и реализует методы для registration_symbol
и registration_priority
(приоритет используется позже для сортировки перечисления), а символ используется в методе create.
Таким образом, я могу опубликовать спецификацию для моих разработчиков, которая показывает им, какие методы Foo реализовать в их подклассах и как зарегистрировать их и где сохранить, а затем приложение Rails автоматически загрузит эти файлы вследующий запуск.