0

我正在尝试使用 CanCan 来限制我网站上的评论可见性。在我的评论模型中定义了一个枚举:

  enum access_right: {nobody: 0, somebody: 1, everyone: 2}

这是我当前的ability.rb 文件的摘录:

class Ability
    include CanCan::Ability

    def initialize(user, session={})
        user ||= User.new # guest user (not logged in)
        # Comments
        can [:create, :read, :update, :destroy], Comment, person_id: person.id
        can [:read], Comment, access_right: [:everyone, Comment.access_rights[:everyone]]
        ...
    end
end

起初我只是在使用:

can [:read], Comment, access_right: 2

但即使这在获取记录时有效:

Comment.accessible_by(...)

对这样的对象检查权限时它不起作用:

can? :read, @a_comment

因为那时@a_comment.access_right ==“每个人”(而不是2)

所以我上网查了一下,发现这个:CanCanCommunity issue 102。建议的解决方案对我不起作用,因为像这样直接使用“每个人”:

can [:read], Comment, access_right: ["everyone", Comment.access_rights[:everyone]]

会给出不正确的结果。获取记录时它背后的 sql 查询如下所示:

SELECT `comments`.* FROM `comments`  WHERE `comments`.`access_right` IN (0,2))

在这种情况下,“每个人”似乎都被转换为整数 (0)。

然后我找到了一个解决方法,我当前的能力文件,这要归功于符号 (:everyone)。但是当使用罐头时,事情将不再起作用?:read, @a_comment (使用accessible_by时sql是正确的)

有谁知道如何纠正这个问题?

如何定义基于枚举的能力,这些能力既可以在获取记录时进行验证,也可以通过 can 进行验证?

谢谢!

编辑:它可能与此CanCanCommunity 问题 65有关,但我无法使其工作。

4

1 回答 1

0

它可以通过CanCan 块语法来实现:

# Please note this is an Array of Strings, not Symbols
allowed_access_rights = %w[everyone] 

can :read, Comment, ["access_right IN (?)", Comment.access_rights.values_at(allowed_access_rights)] do |comment|
  comment.access_right.in? allowed_access_rights
end

尽管在模型上定义范围并将其传递到此处而不是使用原始 SQL 条件是很诱人的,例如:

can :read, Comment, Comment.with_access_right(allowed_access_rights) do |comment| … end

这实际上是一个糟糕的主意,因为它的灵活性要差得多,请参阅CanCan 文档

于 2015-01-19T22:54:05.290 回答