gpt4 book ai didi

activeadmin - 如何避免 Pundit 政策中的 N+1 显示?/更新?/销毁?

转载 作者:行者123 更新时间:2023-12-04 13:35:31 24 4
gpt4 key购买 nike

我将 ActiveAdmin gem 与 Pundit(和 Rolify) gem 一起使用。

这就是我写我的政策的方式(取自:https://github.com/activeadmin/activeadmin/blob/master/spec/support/templates/policies/application_policy.rb):

class ApplicationPolicy
attr_reader :user, :record

def initialize(user, record)
@user = user
@record = record
end

def show?
scope.where(id: record.id).exists?
end

def create?
user.has_role?(:staff, record.company)
end

def update?
scope.where(id: record.id).exists?
end

def destroy?
scope.where(id: record.id).exists?
end

def destroy_all?
true
end

def scope
Pundit.policy_scope!(user, record.class)
end

class Scope
attr_reader :user, :scope

def initialize(user, scope)
@user = user
@scope = scope
end

def resolve
if user.admin?
scope.all
else
company_ids = Company.with_role(:staff, user).map(&:id)
scope.where(company_id: company_ids)
end
end
end
end

这会导致每次 N+1 查询 scope.where(id: record.id).exists? .在索引页, show? , update?destroy?为表中的每条记录调用。

在这种情况下如何避免 N+1 查询?

我试图:
1) 包括/预加载角色与用户一起调用 current_user2) 我正在尝试记住 scope或者使用一些数组方法来防止使用 where 击中数据库和 exists?方法。但是 scope.find仍然对每个新行进行数据库查询。

谢谢!

最佳答案

首先,我建议在 User 中添加一个方法反对在员工帮助的地方返回 company_ids。

class User #or AdminUser right?
def company_ids
@company_ids ||= Company.with_role(:staff, self).map(&:id)
end
end

比你能改变
 def destroy?
scope.where(id: record.id).exists?
end

 def destroy?
return true user.admin?
user.company_ids.include?(record.company_id)
end
Scope 的解析方法现在看起来像这样
def resolve
if user.admin?
scope.all
else
scope.where(company_id: user.company_ids)
end
end
end

关于activeadmin - 如何避免 Pundit 政策中的 N+1 显示?/更新?/销毁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62303449/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com