Как Rails находит модели и контроллеры?Как я могу получить его, чтобы загрузить больше моделей? - PullRequest
3 голосов
/ 26 декабря 2010

Я пытаюсь создать не-ActiveRecord модель в app/models/gamestate.rb.Тогда внутри моего контроллера (PlayController) я смогу сделать GameState.new, верно?Не идти:

NameError (uninitialized constant PlayController::GameState):
  app/controllers/play_controller.rb:23:in `play'

(по крайней мере, в среде разработки)

Но!Если у меня есть модель с именем app/models/play.rb, она автоматически загружается, и я могу выполнить Play.new.

Поэтому мой вопрос: как Rails узнает, какие классы загружать?Какого рода искажение имен он делает, чтобы получить от play#action до PlayController до app/controllers/play_controller.rb до app/models/play.rb?

Это кажется очень хрупким, но, возможно, лучшее понимание того, как это работает, поможет.

И, наконец, как я могу загрузить его app/models/gamestate.rb?

Ответы [ 3 ]

10 голосов
/ 26 декабря 2010

Хейкки прав, но не объясняет почему так.Rails добавляет каждую папку внутри app в конфигурационный параметр autoload_path.Когда запрашивается неизвестная константа, Rails ищет в этом пути константу, и если он не может найти имя файла - например, в случае gamestate.rb против правильного game_state.rb - тогда он выигрываетневозможно загрузить константу, определенную в этом файле.

6 голосов
/ 27 декабря 2010

Чтобы расширить ответ Райана, это соглашение Rails. В Rails 3, activesupport / lib / dependencies.rb имеет метод load_missing_constant, который будет искать GameState, когда вы ссылаетесь на него, и он еще не загружен. Он принимает отсутствующую константу GameState, вызывает подчеркивание, которое преобразует ее в game_state, а затем ищет ее в autoload_paths. Если он находит файл с таким именем (оканчивающийся на .rb), он загружает его.

В производственном режиме game_state.rb будет загружен сразу (при условии, что он находится в одном из autoload_paths), поэтому константа класса GameState уже будет загружена к моменту обращения к ней. В этом случае не нужно калечить.

Возможно, вы захотите поместить не-AR модели в отдельную папку; например, вы можете добавить к путям автозагрузки в config / application.rb, например:

config.autoload_paths += %W(#{config.root}/lib)

Тогда вы можете поместить класс GameState в lib / game_state.rb, и Rails найдет его.

Кстати, я не эксперт по Rails, но один из способов выяснить это - запустить отладчик Ruby и установить точки останова, где, кажется, происходит «волшебство»; затем вы можете использовать where или caller (0), чтобы вернуться и найти соответствующий код Rails. Иногда требуется несколько попыток со стратегическими точками останова (или путем добавления отладчика к исходному коду), но обычно это имеет смысл, когда вы видите, что это происходит построчно.

6 голосов
/ 26 декабря 2010

Если имя файла модели - gamestate.rb, тогда имя класса должно быть Gamestate, а не GameState (или game_state.rb -> GameState). Соглашение об именах Thats Rails. Я рекомендую следовать им, где это возможно. Вещи идут намного более свободно таким образом.

Статья о соглашениях по присвоению имен в Ruby / Rails: http://itsignals.cascadia.com.au/?p=7

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...