ruby-on-rails - 检查数组中每条记录的康康康能力是否正确?

标签 ruby-on-rails ruby postgresql cancancan

从数据库的角度来看。 例如,我在页面(文章)上有 30 条记录,我想检查是否可以创建“赞”。因此,将对数据库进行 30 次查询以检查此能力。执行此类能力检查的最佳做法是什么?

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

更新:添加 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

然后进行查询(您必须查看该文章是否属于用户 friend 的收藏)。

无论在什么情况下,都无法避免向每篇文章询问权限,当然,除非您只加载用户可以“喜欢”的文章,那么就没有必要询问 ;)。

编辑:

让我们检验一下你的能力.rb

if user.admin?
  can :manage, :all

User.admin?假设是管理员?只是一个属性,那么它已经被加载,并且没有进行额外的查询。

然而,exists?查询数据库,它搜索一个类似的关联用户和文章。

  can :create, Like do |like|
    !Like.exists?(user: user, article: like.article)

正如我之前所说,没有办法避免这种情况,除非您在@article 集合中进行一些操作。

我能想到的一个高级想法是在一个数据库事务中加载@articles_liked 和@articles_no_like,然后将它们混合显示,这需要一些工作。

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

相关文章:

node.js - 如何将heroku cedar-14堆栈应用程序升级到最新的heroku堆栈(即heroku 18)

javascript - 在 Sinatra 应用程序中将 Ruby 数据发送到 Javascript

ruby-on-rails - 带有 'as' 参数的 Rails 命名空间路由

sql - JSON 上的 PostgreSQL 索引

ruby-on-rails - 自动跟踪 Rails 中的模型更改

html - 如何从静态页面向 Rails 应用程序提交表单内容?

javascript - 在 Rails ActiveAdmin 中使用 D3

ruby-on-rails - "Not found. Authentication passthru."错误。设计 Omniauthable 模块不会在另一个引擎中使用 't work when it' s

sql - 添加新列 SQL 查询

postgresql - 如何在 Postgresql 11 中使用流复制在主节点上清空 FULL