Need help with Ruby on Rails? Schedule a Free Consultation with our Experts.
Learn More

How to pass additional arguments to policy in Pundit gem

How to authorize the application using pundit gem, basic usage and how to pass additional arguments to the policy class in rails

Posted by Ameena on 08 Sep 2019
How to pass additional arguments to policy in Pundit gem

Pundit provides authorization to the application.

Installation

Add this to your Gemfile

gem 'pundit'
bundle

Usage

Pundit is focused around the notion of policy classes. A simple example of how to use policy is as shown below

class UserPolicy
  attr_reader :user, :record

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

  def create?
    user.super_admin?
  end
end
  1. UserPolicy is the class name where User is the model and Policy is suffixed to it. This format should be followed when creating a policy.

  2. First argument is the current_user. Pundit calls the current_user method to get the result.

  3. Second argument is the model object.

  4. Method name in the policy class should be same as controller action. If the method name is not same then you should write in the controller the name as second argument.

How to use pundit in controller

  1. If controller action is same as policy method

Authorize method automatically starts looking for UserPolicy class and method as create? from action name

class UsersController < ApplicationController
  ...

  def create
    @user = User.build(parameters)
    authorize @user # Authorizing here
    if @user.save
      redirect_to users_path
    else
      render :new
    end
  end
end
  1. If controller action is not same as policy method

Authorize method automatically starts looking for UserPolicy class and method as create? because it is passed explicitly

class UsersController < ApplicationController
  ...

  def invite
    @user = User.find(params[:id])
    authorize @user, :create? # Authorizing here
    ...
  end
end

How to pass additional arguments to policy

Pundit does not allow to pass additional arguments to policy class but in the cases where we have to pass additional arguments, you can use special wrapper class and pass it to policy.

If I have to pass organization_id(field) to policy, I will do as below

class UserContext
  attr_reader :user, :organization_id

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

class ApplicationController
  include Pundit

  def pundit_user
    UserContext.new(current_user, request.organization_id)
  end
end

Using that in a policy will be

class ProjectPolicy < ApplicationPolicy
  def show?
    user.user.admin? && user.user.organization_id == user.organization_id
  end
end

Here I am allowing only the user who is admin and is same organization as the organization I am passing in the parameter to see the project page.

Keep Coding !!!

Contact us to work on your website.

- Ameena


Need help with Ruby on Rails? Schedule a Free Consultation with our Experts.
Learn More

Related Services.



Hire ReactJS Developers
Hire Gatsby Developers
Hire NextJS Developers

We support the Open Source community.



Have a Project in mind?