从数据库的角度来看。
例如,我在页面(文章)上有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/