Проблемы с отражением в Rails - PullRequest
1 голос
/ 02 августа 2010

У меня есть приложение 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), но я бы по крайней мере хотел бы знать , почему этот метод не работает.Может ли кто-нибудь пролить свет (или, что еще лучше, заставить его работать)?

1 Ответ

1 голос
/ 03 августа 2010

да, к сожалению, active_support «по требованию», а не «по требованию», поэтому вам, вероятно, придется использовать ваш preloader.К сожалению, если ваше приложение находится в режиме разработки, оно, вероятно, настроено на «перезагрузку классов при каждом запросе», поэтому вам придется отключить эту удобную функцию rails или обязательно перезагрузить эти файлы при необходимости.

-r

...