我有一个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框架存在一些冲突
答案 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的子类但是覆盖了相关的方法,那么它不会覆盖你的用例吗?