首先加载全局应用程序控制器时,在该名称空间中加载页面时,不会加载命名空间的应用程序控制器。应用程序控制器如下所示:
class ApplicationController < ActionController::Base
protect_from_forgery
end
命名空间的应用程序控制器如下所示:
class Admin::ApplicationController < ApplicationController
def authenticate_admin!
if current_admin.nil?
redirect_to new_admin_session_url
end
end
private
def current_admin
@current_admin ||= Admin.find(session[:admin_id]) if session[:admin_id]
end
helper_method :current_admin
end
当我们使用before_filter“authenticate_admin!”时像这样:
class Admin::AssetsController < Admin::ApplicationController
before_filter :authenticate_admin!
end
抛出“Admin :: AssetsController #new中的NoMethodError”。仅当我们在命名空间路由之前命中全局路由时才会发生这种情况。如果服务器重新启动并且加载了命名空间路由,则一切正常。
答案 0 :(得分:9)
这种情况正在发生,因为您碰巧拥有一个与您的命名空间同名的Admin
模型(一个类)。
This Google小组帖子很好地解释了究竟发生了什么。
要修复,我会将模型重命名为AdminUser
,或者如果不可能,重命名命名空间也可以解决问题。
答案 1 :(得分:3)
命名空间控制器需要出现在正确的目录结构中。
app/controllers/admin/application_controller.rb
app/controllers/admin/assets_controller.rb
就个人而言,我建议不要为命名空间的基本控制器重载ApplicationController
名称。这不会导致问题,但这是一个偏好问题 - 只有一个应用程序,应该只有一个ApplicationController
。如果这是ContentManagementController
命名空间的目的,则可以使用Admin
。
其次,最好使用module
关键字并以这种方式定义控制器:
module Admin
class ContentManagementController < ApplicationController
# ..
end
end
# app/controllers/admin/content_management_controller.rb
编辑:我刚刚看到了具体的错误(也许您的问题已更新?) - 您需要在AssetsController
上定义新操作
def new
#
end