【问题标题】:Load models filtered using has_many relation加载使用 has_many 关系过滤的模型
【发布时间】:2013-06-05 19:58:46
【问题描述】:

我想根据嵌套资源的属性过滤模型,例如:

can :read, Model, has_many_relation: { attribute: attr }

使用这种形式的块的问题:

can :read, Model do |obj|
    obj.has_attribute(attr)
end

是该权限只能在获取单个模型时使用(调用加载#index操作时忽略该权限)。

如何使用基于 has_many 关系的条件过滤模型?

【问题讨论】:

    标签: ruby-on-rails activerecord cancan


    【解决方案1】:

    我使用 CanCan 已经很多年了,我只是解决了这个问题。伪代码有点棘手,但希望这能让你到达那里。

    can :read, Model, Model.joins(:has_many_relation).where(has_many_table: { attribute: attr }) do |model|
      model.has_many_relation.pluck(:attribute).include?(attr)  
    end
    

    一个更具体的示例(仅读取用户user.widgets 范围内的小部件)可能更容易理解:

    can :read, Widget, user.widgets do |widget|
      user.widgets.include?(widget)
    end
    

    一般的想法是你必须包含 both 一个 SQL 查询(用于查询所有可访问的模型),一个块(用于检查单个模型的权限) .

    而且,为了记录,我们一直在寻找的示例实际上已经在 the docs 中。

    【讨论】:

    • 尝试了第二种解决方案,但由于某种原因出现了缺少方法的错误:(未定义的方法 `include?' for #<0x007fd6968eceb0>
    【解决方案2】:

    如果您使用 CanCan >= 1.6,则可以使用范围。

    can :read,
      Model,
      Model.joins(:has_many_relation)
           .where(:has_many_table => { :attribute => attr }) 
    

    【讨论】:

    • 如果你构建这样的规则,can? :read, Model 会给你CanCan::Error: The can? and cannot? call cannot be used with a raw sql 'can' definition. The checking code cannot be determined for :show #&lt;Model...。到目前为止,我还没有找到一种有效的方法来做到这一点。
    • 你只是错过了一个块。
    【解决方案3】:

    为了通过has_many关系中的属性进行过滤,基本的hash of conditions就可以了。

    用于提出问题的第一个示例有效:

    can :read, Model, has_many_relation: { attribute: attr }
    

    只要确保模型具有相应的 has_many 关系,并且 has_many 表包含属性引用的列即可:

    【讨论】:

      猜你喜欢
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-30
      相关资源
      最近更新 更多