Pundit::Before
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.