Migrate from Pundit to Action Policy
Migration from Pundit to Action Policy could be done in a progressive way: first, we make Pundit polices and authorization helpers use Action Policy under the hood, then you can rewrite policies in the Action Policy way.
Phase 1. Quacking like a Pundit
Step 1. Prepare controllers
Remove
include Punditfrom ApplicationControllerAdd
authorizemethod:
def authorize(record, rule = nil)
options = {}
options[:to] = rule unless rule.nil?
authorize! record, **options
endConfigure authorization context if necessary, e.g. add
authorize :current_user, as: :usertoApplicationController(NOTE: added automatically in Rails apps)Add
policyandpolicy_scopehelpers:
helper_method :policy
helper_method :policy_scope
def policy(record)
policy_for(record: record)
end
def policy_scope(scope)
authorized scope
endNOTE: policy defined above is not equal to allowed_to? since it doesn't take into account pre-checks.
Step 2. Prepare policies
We assume that you have a base class for all your policies, e.g. ApplicationPolicy.
Then do the following:
Add
include ActionPolicy::Policy::CoretoApplicationPolicyUpdate
ApplicationPolicy#initialize:
def initialize(target, user:)
# ...
endUnfortunately, there is no easy way to migrate Pundit class-based scope to Action Policies scopes.
Step 3. Replace RSpec helper
We provide a Pundit-compatible syntax for RSpec tests:
# Remove DSL
# require "pundit/rspec"
#
# Add Action Policy Pundit DSL
require "action_policy/rspec/pundit_syntax"Phase 2. No more Pundit
When everything is green, it's time to fully migrate to ActionPolicy:
- make ApplicationPolicy inherit from
ActionPolicy::Base - migrate view helpers (from
policy(..)toallowed_to?, frompolicy_scopetoauthorized) - re-write specs using simple non-DSL syntax (or Action Policy RSpec syntax)
- add authorization tests (add
require 'action_policy/rspec') - use Reasons, I18n integration, cache and other Action Policy features!