pundit icon indicating copy to clipboard operation
pundit copied to clipboard

[Request] policy_scope should not alter joined table structure

Open jamesst20 opened this issue 3 years ago • 1 comments

Hi,

I believe there is a very small improvement that could be implemented in Pundit's policy_scope.

Exemple of problem

  class Scope < ::ApplicationPolicy::Scope
    def resolve 
     # I know the joins are being useless, it's only for demo
      scope.left_joins(:user, project: :project_managers).where(user: { id: 9 })
    end
  end
policy_scope(ProjectTime).where(date: @date).sum(:total)
=> 8.28111111111111

policy_scope(ProjectTime).distinct.where(date: @date).sum(:total)
=> 6.519722222222221

Problem

Some results in the SQL query are duplicated because of the joined table.

Solution

An easy way to come around this issue is to wrap the policy in a subquery like so

class Scope < ::ApplicationPolicy::Scope
    def resolve 
      scoped = scope.left_joins(:user, project: :project_managers).where(user: { id: 9 })
      scope.where(id: scoped)
    end
  end
policy_scope(ProjectTime).where(date: @date).sum(:total)
=> 6.519722222222221

policy_scope(ProjectTime).distinct.where(date: @date).sum(:total)
=> 6.519722222222221

Request

I believe this behavior could be wrapped into the gem and applied automatically. I believe it also make sense that our policies only take care of filtering stuff without leaving any side effect.

jamesst20 avatar Nov 16 '22 23:11 jamesst20

Just opened PR #749

Edit: Just noticed the build failed. Likely because Pundit is not specific to ActiveRecord. Leaving it there just in case you have a better implementation in mind.

jamesst20 avatar Nov 16 '22 23:11 jamesst20

See https://github.com/varvet/pundit/pull/749#issuecomment-1463693064

Burgestrand avatar Mar 10 '23 11:03 Burgestrand