PBJ*_*PBJ 3 ruby activerecord ruby-on-rails
我正在尝试创建一个非ActiveRecord模型app/models/gamestate.rb.然后在我的控制器(PlayController)里面,我应该可以做到GameState.new,对吧?不去:
NameError (uninitialized constant PlayController::GameState):
app/controllers/play_controller.rb:23:in `play'
Run Code Online (Sandbox Code Playgroud)
(至少在开发环境中)
但!如果我确实有一个名为的模型app/models/play.rb,那么它会自动加载,我可以做Play.new.
所以我的问题是:Rails如何知道要加载哪些类?它能做什么样的名字改编的摆脱play#action到PlayController到app/controllers/play_controller.rb到app/models/play.rb?
它似乎非常脆弱,但也许更好地了解它的工作原理会有所帮助.
最后,我怎样才能加载它app/models/gamestate.rb?
Rya*_*igg 10
Heikki是对的,但没有解释为什么会这样.Rails将每个文件夹添加app到autoload_path配置设置中.当一个未知的常量被要求时,Rails会在这条路径中查找常量,如果它找不到文件名 - 比如gamestate.rb正确的情况game_state.rb- 则它将无法加载此文件中定义的常量.
如果模型文件名是gamestate.rb,那么类名应该是Gamestate而不是GameState(或者game_state.rb - > GameState).多数民众赞成Rails命名约定.我建议尽可能遵循它们.事情就这样流畅得多.
关于Ruby/Rails命名约定的文章:http://itsignals.cascadia.com.au/?p = 7
为了扩展Ryan的答案,这是一个Rails惯例.在Rails 3中,activesupport/lib/dependencies.rb有一个名为load_missing_constant的方法,当你引用GameState并且尚未加载时它会查找GameState.它需要丢失常量'GameState',在其上调用'下划线'将其转换为game_state,然后在autoload_paths中搜索它.如果它找到具有该名称的文件(以.rb结尾),则会加载它.
在生产模式中,game_state.rb将被预先加载(假设它在一个autoload_paths中),因此GameState类常量将在您引用它时加载.在这种情况下不需要修剪.
您可能希望将非AR模型放在单独的文件夹中; 例如,您可以添加到config/application.rb中的自动加载路径,例如:
config.autoload_paths += %W(#{config.root}/lib)
Run Code Online (Sandbox Code Playgroud)
然后你可以把类GameState放在lib/game_state.rb中,Rails会找到它.
顺便说一句,我不是Rails专家,但是解决这个问题的一种方法是运行Ruby调试器并设置断点,其中"魔术"似乎发生; 然后你可以使用where或caller(0)来回溯并找到相关的Rails代码.有时需要花几次尝试使用策略断点(或者通过在源代码中添加调试器),但是一旦看到它逐行发生,通常就会有意义.