0.0
No release in over a year
Adds before hook to pundit policy classes
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

>= 2.0, < 3.0
 Project Readme

Pundit::Before

CI

Adds before hook to pundit policy classes to resolve things like varvet/pundit#474. Inspired by action_policy pre-checks.

Installation

Add this line to your application's Gemfile:

gem "pundit-before"

And then execute:

bundle install

Usage

Use allow! inside callback method or block to return true without evaluating edit? method defined in policy.

class UserPolicy < ApplicationPolicy
  include Pundit::Before

  before :check_admin

  def edit?
    false
  end

  private

  def check_admin
    allow! if user.admin?
  end
end

UserPolicy.new(User.new(admin: true), record).edit?  # => true
UserPolicy.new(User.new(admin: false), record).edit? # => false

Use deny! inside callback method or block to return false without evaluating edit? method defined in policy.

class UserPolicy < ApplicationPolicy
  include Pundit::Before

  before :check_admin

  def edit?
    true
  end

  private

  def check_admin
    deny! unless user.admin?
  end
end

UserPolicy.new(User.new(admin: true), record).edit?  # => true
UserPolicy.new(User.new(admin: false), record).edit? # => false

Internally before hook is implemented as ActiveSupport::Callbacks, so the callback chain will halt if do any call to allow! or deny! method. It's similar as Rails controller action filters works.

block form

class UserPolicy < ApplicationPolicy
  include Pundit::Before

  before do
    allow! if user.admin?
  end

  def edit?
    false
  end
end

skip before hook

class UserPolicy < ApplicationPolicy
  include Pundit::Before

  before :check_admin

  def edit?
    false
  end

  private

  def check_admin
    allow! if user.admin?
  end
end

class OperatorPolicy < UserPolicy
  skip_before :check_admin
end

UserPolicy.new(User.new(admin: true), record).edit?     # => true
OperatorPolicy.new(User.new(admin: true), record).edit? # => false

using only modifier

class UserPolicy < ApplicationPolicy
  include Pundit::Before

  before :check_admin, only: :update?

  def edit?
    false
  end

  private

  def check_admin
    allow! if user.admin?
  end
end

UserPolicy.new(User.new(admin: true), record).edit? # => false

using except modifier

class UserPolicy < ApplicationPolicy
  include Pundit::Before

  before :check_admin, except: :edit?

  def edit?
    false
  end

  def destroy?
    false
  end

  private

  def check_admin
    allow! if user.admin?
  end
end

UserPolicy.new(User.new(admin: true), record).edit?    # => false
UserPolicy.new(User.new(admin: true), record).destroy? # => true

calling multiple methods

class UserPolicy < BasePolicy
  before :check_presence, :check_admin

  def edit?
    false
  end

  private

  def check_presence
    deny! unless user.present?
  end

  def check_admin
    allow! if user.admin?
  end
end

UserPolicy.new(nil, record).edit?                    # => false
UserPolicy.new(User.new(admin: false), record).edit? # => false
UserPolicy.new(User.new(admin: true), record).edit?  # => true

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bin/rake install.

To release a new version, update the version number in version.rb, and then run bin/rake release, which will create a git tag for the version, push git commits and the created tag, and push the .gem file to rubygems.org.

License

Copyright © 2023 Javier Aranda. Released under the terms of the MIT license.