如何在Pundit中为非同名控制器授权指定资源?
解决Pundit中控制器与资源类不匹配时的授权问题
当你需要在控制器(比如SomeOtherBlogsController)中使用与资源类(Blog)不匹配的Policy(SomeOtherBlogPolicy)时,Pundit提供了两种简洁的解决方式,下面分别说明:
方法1:全局指定控制器的默认Policy类
如果整个控制器的所有动作都需要使用同一个自定义Policy,直接在控制器中重写pundit_policy_class方法即可。这样每次调用authorize时,Pundit都会使用你指定的Policy类,而不是根据资源自动推断:
class SomeOtherBlogsController < ApplicationController before_action :check_authorization # 重写该方法指定默认Policy类 private def pundit_policy_class SomeOtherBlogPolicy end def check_authorization # 现在调用authorize @blog时,会使用SomeOtherBlogPolicy authorize @blog end end
对应的SomeOtherBlogPolicy可以正常接收current_user和@blog(作为record参数):
class SomeOtherBlogPolicy < ApplicationPolicy def show? # 这里可以通过user访问current_user,record访问@blog user.has_permission_to_view?(record) end end
方法2:针对单个授权动作指定Policy类
如果只是某个特定动作或授权场景需要使用不同的Policy,可以在调用authorize时通过policy_class选项直接指定:
class SomeOtherBlogsController < ApplicationController before_action :check_authorization private def check_authorization # 明确指定使用SomeOtherBlogPolicy来检查@blog的权限 authorize @blog, policy_class: SomeOtherBlogPolicy end end
这种方式更灵活,适合控制器中存在多种授权策略的场景。
为什么你原来的写法不生效?
你之前尝试的authorize :some_other_blog, @blog不符合Pundit的参数规则:第一个参数传入Symbol时,Pundit会将其视为**范围授权(scope authorization)**的标识,而不是指定Policy类。因此这种写法无法触发SomeOtherBlogPolicy的检查逻辑,需要改用上面两种正确的方式。
内容的提问来源于stack exchange,提问作者Neil
相关产品推荐
相关产品推荐

