Setup Pundit in Rails
Install gem
./bin/bundle add pundit
Configure Pundit
Include the Pundit module in ApplicationController.
class ApplicationController < ActionController::Base
include Pundit::Authorization
end
Generate default application policy
./bin/rails g pundit:install
This will create a new file: app/policies/application_policy.rb.
Restart Rails server.
Add policy
You typically create a policy for each model in your app. For example, supposing you have a Post mode, you’ll want to create a PostPolicy at app/policies/post_policy.
./bin/rails g pundit:policy Post
class PostPolicy
attr_reader :user, :post
def initialize(user, post)
@user = user
@post = post
end
def update?
user.admin? || !post.published?
end
end
In a controller, you can do something like:
def update
@post = Post.find(params[:id])
authorize @post
if @post.update(post_params)
redirect_to @post
else
render :edit
end
end
Thanks to naming conventions, Pundit will take the authorize @post invocation and do something like this:
unless PostPolicy.new(current_user, @post).update?
raise Pundit::NotAuthorizedError, "not allowed to update? this #{@post.inspect}"
end
(Bonus) Add a owner? method
You often need to only grant permission if a user owns a resource. To keep things DRY, consider adding a owner? method to the base ApplicationPolicy (app/policies/application_policy.rb).
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
## other methods
def owner?
user.id === record.user_id
end
end
Now, you can just reuse this method in each model policy. For example, suppose you have QuotePolicy.
# frozen_string_literal: true
class QuotePolicy < ApplicationPolicy
def edit?
owner?
end
def update?
owner?
end
# And so on...
end
Sources
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment