Pundit policies with two input parameters

Relying on more than the current user and a domain model is a code smell, but in case it really is required, then you can use a custom query method with any number of parameters and raise an exception if the requirements don't met:

class BarPolicy < ApplicationPolicy
  def authorize_test?(foo)
    raise Pundit::NotAuthorizedError, "not authorized to test" unless record.foo_id == foo
  end
end

class BarsController < ApplicationController
  def test
    skip_authorization && BarPolicy.new(current_user, @record).authorize_test?(@foo)
    ...
  end
end

The skip_authorization && part is not required if after_action :verify_authorized is not used, I just wanted to show a one-liner that can be used in this case to get rid of the not-authorized exception while still having the requirement to authorize the action.


I found the answer at here.

Here is my way:

Add a pundit_user function in ApplicationController:

class ApplicationController < ActionController::Base
include Pundit
def pundit_user
    CurrentContext.new(current_user, foo)
end

Create the CurrentContext class:

/lib/pundit/current_context.rb
class CurrentContext
  attr_reader :user, :foo

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

Update the initialize Pundit method.

class ApplicationPolicy
  attr_reader :user, :record, :foo

  def initialize(context, record)
    @user = context.user
    @foo = context.foo
    @record = record
  end
end