从数据库的角度来看。
例如,我在页面(文章)上有30条记录,我想检查是否可以创建“Like”。因此,将有30个查询到数据库来检查这种能力。执行这种能力检查的最佳实践是什么?

<% @articles.each do |article| %>
  <% if can? :create, Like.new(user: user, article: article) %>
      <%= link_to "Like!", like_path(article) %>
  <% end %>
<% end %>

更新:Add ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new
    if user.admin?
      can :manage, :all
    else
      can :create, Like do |like|
        !Like.exists?(user: user, article: like.article)
      end
    end
  end
end

最佳答案

能力本身并不存储在数据库中。这里有一个example

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)
    if user.admin?
      can :manage, :all
    else
      can :read, :all
    end
  end
end

如您所见,它不触及数据库,因为您已经有了一个用户变量,您只需要询问一个属性。
在您的示例中,我假设您已经加载了一个“用户”,当然,您已经获取了许多文章。
如果你取消能力,例如:
  user ||= User.new
  can :manage, Article do |a|
      a.user_id== user.id
    end

然后不进行任何查询,因为您已经拥有了关于一篇文章的所有信息。
但是,如果您必须加载额外的信息,例如
  can :manage, Article do |i|
      user.friends_articles.exists?(i.id)
    end

然后进行查询(您必须查看文章是否属于用户朋友的收藏)。
无论是哪种情况,都无法逃避向每一篇文章请求权限,当然,除非您只加载用户可以“喜欢”的文章,那么,就不需要请求;)。
编辑:
让我们检查一下你的能力
if user.admin?
  can :manage, :all

用户管理?,担任管理员?只是一个属性,然后它已经被加载,并且不会进行其他查询。
然而,exists?查询数据库,它搜索相似的关联用户和文章。
  can :create, Like do |like|
    !Like.exists?(user: user, article: like.article)

正如我之前所说,除非您在@article集合中进行一些操作,否则无法避免这种情况。
我能想到的一个先进的想法是在一个数据库事务中加载@ ToeStLeWype和@ ToeStReNoSUI,然后将它们混合起来进行显示,这就需要一点工作。

关于ruby-on-rails - 检查数组中每个记录的cancancan能力是否正确?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43125686/

10-09 21:02