У меня есть приложение Rails, представляющее карточную игру.Есть несколько разных типов карт и несколько расширений для игры, каждый из которых предоставляет больше карт.Поэтому я использую одну таблицу cards
и STI, причем каждое расширение имеет подкаталог моделей и модуль с соответствующим именем.Например:
app/models
- card.rb
+ base_game
- foo.rb
- class BaseGame::Foo < Card
- bar.rb
- class BaseGame::Bar < Card
+ exp_one
- thing.rb
- class ExpOne::Thing < Card
Это хорошо работает.
Я бы хотел получить список всех карт в каждом расширении.Метод constants
для Module
обеспечивает удобный способ сделать это -
class Card
def self.base_game_cards
BaseGame.constants.map {|c| ("BaseGame::" + c).constantize}.select {|c| c.instance_of?(Class) and c.superclass == Card}
end
end
... за исключением того, что Rails загружает только данное определение модели при первой ссылке, поэтому Card.base_game_cards
обычно []
.
Я попытался обойти это, принудительно предварительно загрузив все модели, добавив файл в config / initializers:
preloader.rb:
# Preload all card models from all expansions. This allows us to dynamically
# determine card types by reflection.
Dir.glob("#{RAILS_ROOT}/app/models/*/*.rb").each do |file|
require file
end
Но, похоже, это тоже не работает, и я не могу понять, почему.Используя raise
и inpect
, я определил, что когда я вызываю Card.base_game_cards
с контроллера, результат все равно обычно []
.Очень редко это правильно сразу после перезапуска сервера, но при обновлении страницы он возвращается на []
.Если я использую script \ console, список всегда верен.Я попытался переместить блок require в начало определения класса контроллера, но это тоже не имеет значения.
Теперь я совершенно готов на этом этапе перейти к другому решению (возможно, просто вразрезсписок имен файлов, возвращаемых glob
), но я бы по крайней мере хотел бы знать , почему этот метод не работает.Может ли кто-нибудь пролить свет (или, что еще лучше, заставить его работать)?