Rails 3.2.3命名空间控制器被具有相同名称的全局控制器覆盖

时间:2012-06-05 17:31:28

标签: ruby-on-rails ruby ruby-on-rails-3.2 controllers nomethoderror

首先加载全局应用程序控制器时,在该名称空间中加载页面时,不会加载命名空间的应用程序控制器。应用程序控制器如下所示:

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”。仅当我们在命名空间路由之前命中全局路由时才会发生这种情况。如果服务器重新启动并且加载了命名空间路由,则一切正常。

2 个答案:

答案 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