Rails+Pundit环境下如何在Policy的Scope中检查类?
在Pundit的Scope中检查STI类的正确做法
完全可以在Policy的Scope中检查类,你的问题主要出在STI字段使用错误和常量引用问题上。
错误原因分析
- Rails单表继承(STI)默认用
type字段存储子类名称,而非你代码里的class字段,这是Active Record的内置约定。 - 直接写
Tropical会导致Policy无法正确解析该常量——要么是Rails自动加载时机未覆盖到,要么是常量作用域的问题。
解决步骤
1. 确认STI字段配置
- 遵循Rails默认约定:确保
fruits表包含type字符串字段(建议长度设为255)。 - 若要自定义为
class字段:在Fruit模型中添加配置:
# app/models/fruit.rb class Fruit < ApplicationRecord self.inheritance_column = 'class' # 指定自定义STI字段名 end
2. 修正Policy中的查询代码
有两种可靠写法:
写法一:直接使用类名字符串(最稳妥,避免常量加载问题)
class FruitPolicy < ApplicationPolicy class Scope < Scope def resolve if user.is_near_equator scope.where(type: "Tropical") # 字段名按你的STI配置选type或class else scope.where(type: "Temperate") end end end end
写法二:通过类名.name获取字符串(更灵活,避免硬编码)
class FruitPolicy < ApplicationPolicy class Scope < Scope def resolve if user.is_near_equator scope.where(type: Tropical.name) else scope.where(type: Temperate.name) end end end end
如果仍出现常量未初始化错误,可在Policy顶部手动加载子类:
require 'tropical' require 'temperate' class FruitPolicy < ApplicationPolicy # ... 后续代码 ... end
内容的提问来源于stack exchange,提问作者nakakapagpabagabag
相关产品推荐
相关产品推荐

