1

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 ?

Deepak Kumar Padhy
  • 4,128
  • 6
  • 43
  • 79

1 Answers1

4

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
hedin
  • 1,004
  • 10
  • 18