Currently we are using two separate table for Users and Roles.
I am using pundit for authorisation and devise for authentication.
At many places I am doing current_user.roles
to fetch the roles of the user. Mostly inside pundit policy files.
I want to store the User roles in the session when user logs in. So that I will not query db each time to fetch the roles.
Any quick solution will be greatly appreciated ?
Since Pundit have no options, to pass session
or other parameter, except current_user
and checking entity
, you can use Rails.cache
instead:
# app/models/user.rb
class User < ActiveRecord::Base
# ...
def cached_roles
Rails.cache.fetch "user.#{self.id}.roles" do
roles.pluck(:name)
end
end
def clear_cached_roles
Rails.cache.delete "user.#{self.id}.roles"
end
end
# app/policies/post_policy.rb
class PostPolicy < ApplicationPolicy
# ...
def admin?
user.cached_roles.include? 'admin'
end
def reader?
user.cached_roles.include? 'reader'
end
end
To make Devise to cache current roles, you need to override Devise's session_controller
# app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
def create
super
current_user.cached_roles
end
def destroy
current_user.clear_cached_roles
super
end
end
I created this demo rails application, you can play with it: see my solution variant with Rails.cache
in rails_cache_solution branch or in pull request.
Also see these files for more details:
app/controllers/users/sessions_controller.rb
spec/controllers/posts_controller_spec.rb
app/policies/post_policy.rb
app/models/user.rb
README.md