如何访问rails中的嵌套控制器?

时间:2015-06-28 18:58:11

标签: ruby-on-rails inheritance module controller nested

我有一个Web应用程序,我想将其扩展到Web API。我已将控制器拆分为2个文件夹Web和Api。我将我的ApplicationController放在Web文件夹中,并希望在api文件夹中有一个ApiController。

我知道ActionController只应该从ApplicationController继承。有没有办法可以使用2个独立的控制器,所以我可以在每个控制器中有不同的行为?

我想要2的一个例子是,我可以用不同的方式处理CanCan异常,并以不同的方式处理protect_from_forgery。

更新

当我尝试运行测试时,我收到以下错误

  

api_sessions_controller.rb:1:in'':uninitialized constant ApiController(NameError)

我的Api会话控制器

class ApiSessionsController < ApiController
    def create
        user_password = params[:session][:password]
        user_email = params[:session][:email]
        user = user_email.present? && User.find_by(email: user_email)

        if user.valid_password? user_password
          sign_in user, store: false
          user.generate_authentication_token!
          user.save
          render json: user, status: 200, location: [:api, user]
        else
          render json: { errors: "Invalid email or password" }, status: 422
        end
    end
end

Api控制器

class ApiController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :null_session

  # include SessionsHelper

  rescue_from CanCan::AccessDenied do |exception|
        if user_signed_in?
            flash[:error] = "Access denied!"
            redirect_to root_url
        else
            flash[:error] = "Please Sign in"
            redirect_to new_user_session_path
        end
    end
end

我对导致这种情况的原因感到茫然,我看不出任何一个控制器出了什么问题,这就是为什么我认为可能与我正在做的事情和rails框架存在一些冲突

2 个答案:

答案 0 :(得分:2)

我同意ABMagil,没有人说你必须继承ApplicationController。在您的情况下,您特别提到您需要不同的访问控制+ CSRF保护,因此它总是有理由让另一个应用程序控制器继承自ActionControlle::Base

无论如何,一切都会在您的路线中发生:

namespace :api do
  # Stuff here will automatically look inside controllers/api/ folder, 
  # URL prefixed with /api/ 
  # View url/path helpers with prefix api_
end
# your_domain.com/api/my_resource/

scope module: 'web' do
  # Stuff here will look for controllers in controllers/web/ 
  # NO URL prefix
  # NO url/path prefix for View helpers
end
# your_domain.com/my_resource

编辑:关于你的错误

当命名空间时,它意味着您将类包装在一个模块中,因此您必须为每个子控制器指定它。即

  • 您可以在ActionController文件夹中拥有ApiController/controller/(我建议您这样做+第3个要点,感觉更清楚)

    controllers/api_controller.rb, 
    controllers/application_controller.rb
    
    class ApiController, class ApplicationController
    
  • 如果要将它们移动到api / web子文件夹,则必须在文件中反映出来

    controllers/api/api_controller.rb, 
    controllers/web/application_controller.rb
    
    class Api::ApiController, class Web::ApplicationController
    
  • 显然,同样尊重你的其他控制器

    controllers/api/session_controller.rb
    
    class Api::SessionController
    

另请注意,如果您想保留API(仅限大写字母),我认为当您使用文件夹名称/API/

时它会起作用

答案 1 :(得分:1)

谁说只有ApplicationController可以/应该从ActionController继承? ApplicationController设置查看文件的路径(与API无关)并定义require_local!local_request?。如果您不使用这些方法(require_local!InfoController在Rails代码库中调用MailersController),那么您就不会丢失任何内容。

如果您的逻辑仅适用于您的API,那么您当然可以直接将ActionController子类化,但这是必要的吗?如果你是ApplicationController的子类但是覆盖了相关的方法,那么它不会覆盖你的用例吗?