更新
我已经尝试__为:specific_trainees
添加另一个sql查询,但是这样做并在两个SQL查询上调用UNION
只会与所有学员共享资源,无论我是否选择:all_trainees
或:specific_trainees
。
我很好奇是否可以在Rails PolicyObject中访问params对象。
下面,我在策略中有一个作用域类
class ResourcePolicy < ApplicationPolicy
def index?
true
end
alias :new? :index?
alias :create? :index?
def destroy?
record.resource_duty == user
end
class Scope < ApplicationPolicy::Scope
def resolve
employee_resources = scope.left_outer_joins(:resource_roles, :resource_locations).where(
'
resource_duty_id IN(?)
AND (permitted_employees = ? OR resource_roles.job_role_id IN(?))
AND (permitted_locations = ? OR resource_locations.location_id IN(?))
',
user.organization_ids,
Resource.permitted_employees[:all_employees], user.job_role_ids,
Resource.permitted_locations[:all_locations], user.location_ids
).where(namespace: 'company')
all_trainees_resources = scope.left_outer_joins(:resource_courses).where(
'resource_duty_id IN(?) AND (permitted_trainees = ? OR resource_courses.course_id IN(?))',
user.training_organization_ids,
Resource.permitted_trainees[:all_trainees],
user.cards.pluck(:course_id)
).where(namespace: 'training_provider')
specific_trainees_resources = scope.left_outer_joins(:resource_courses).where(
'resource_duty_id IN(?) AND (permitted_trainees = ? OR resource_courses.course_id IN(?))',
user.training_organization_ids,
Resource.permitted_trainees[:specific_trainees],
user.cards.pluck(:course_id)
).where(namespace: 'training_provider')
cardholder_resources = scope.where(resource_duty: user)
# NOTE: this is all a bit hackey. It might be worth using the sequel gem to improve this
sql = Resource.connection.unprepared_statement {
"((#{employee_resources.to_sql}) UNION (#{all_trainees_resources.to_sql}) UNION (#{specific_trainees_resources.to_sql}) UNION (#{cardholder_resources.to_sql})) AS resources"
}
Resource.from(sql)
end
end
end
我想根据传递的参数将 Resource.permitted_trainees[:all_trainees]
更改为 Resource.permitted_trainees[:specific_trainees]
。
谢谢!
答案 0 :(得分:1)
我假设当您说“ Rails PolicyObject”时,是指“ Pundit Policy”,而不是您正在使用的本地解决方案。
也就是说,有可能,尽管Pundit团队不建议这样做。
请参见this section of the docs,该指南实质上建议您执行以下操作:
class UserContext
attr_reader :user, :show_all_trainees
def initialize(user, show_all_trainees)
@user = user
@show_all_trainees = show_all_trainees
end
end
class ApplicationController
include Pundit
def pundit_user
UserContext.new(current_user, request.show_all_trainees)
end
end
对于您的问题而言,更直接的答案是,我认为更好的方法不是传递参数,而是使用顺序应该已经拥有的User
对象或Trainee
策略确定要显示哪些受训者。
您可以执行以下操作:
trainee_resources = scope.left_outer_joins(:resource_courses).where(
'resource_duty_id IN(?) AND (permitted_trainees = ? OR resource_courses.course_id IN(?))',
user.training_organization_ids,
policy_scope(Trainee),
user.cards.pluck(:course_id)
).where(namespace: 'training_provider')
您还可以根据类似if
角色或其他属性的变量定义,对变量定义进行简单的User
声明,以表明他们应该访问哪些受训者。
没有关于您的应用程序体系结构的更多信息,很难过于具体,但是希望其中一种方法可以引导您找到所需的解决方案!