命名空间控制器引用顶级模型:
class AdminArea::WelcomeController < ApplicationController def index @user = User.new(name: 'Sergio') end end
到现在为止还挺好.您可以查看主服务器,导航到http:// localhost:3000 / admin_area / welcome并查看它是否有效.
但是如果我们were to add an empty directory app/presenters/admin_area/user/
*,那么事情会变得奇怪.突然之间,该控制器中的用户不是我的模型,而是一个不存在的模块!
NoMethodError (undefined method `new' for AdminArea::User:Module): app/controllers/admin_area/welcome_controller.rb:3:in `index'
当然,该模块没有任何[非内置]方法,也无法固定到磁盘上的源文件中.
问题:为什么添加一个空目录导致rails神秘地通过空气神秘地召唤一个模块,而不是正确地将用户名解析为我的模型?
*实际上,如果您按原样检查该分支,您将收到不同的错误.
NameError (uninitialized constant AdminArea::WelcomeController::User)
解决方法
控制器中的常量用户称为“relative reference”,这意味着它应该相对于其发生的命名空间进行解析.
对于此常量,有三种可能的变量,其中可以定义常量:
AdminArea::WelcomeController::User AdminArea::User User
Rails自动加载将这些常量映射到文件名中并在autoload_path
上进行迭代,以便找到定义常量的文件.例如.:
app/assets/admin_area/welcome_controller/user.rb app/assets/admin_area/welcome_controller/user app/channels/admin_area/welcome_controller/user.rb ... app/assets/admin_area/user.rb app/assets/admin_area/user ... app/assets/user.rb ... app/models/user.rb #=> here it is!
将admin_area / user文件夹添加到presenters目录中时,您实际上是在定义这样的常量. Modules in Rails are automagically created,这样您实际上不需要创建定义这些仅用作命名空间的模块的文件.
... app/assets/admin_area/user.rb app/assets/admin_area/user ... app/presenters/admin_area/user #=> Here Rails finds the folder
和Rails解析用户引用该模块.
但是,这很容易修复,如果您希望AdminArea命名空间中使用的User常量引用顶级常量(而不是AdminArea :: User模块),则应将“相对引用”更改为绝对引用通过在::之前加上常量.
@user = ::User.new(name: 'Sergio')