如何自定义设计以在会话中存储用户角色信息?

How to customise devise to store user role information in session?

目前我们为用户和角色使用两个单独的 table。

我正在使用 pundit 进行授权并使用 devise 进行身份验证

在很多地方我都在current_user.roles获取用户的角色。主要在权威政策文件中。

我想在用户登录时将用户角色存储在会话中。这样我就不会每次都查询数据库来获取角色。

任何快速解决方案将不胜感激?

由于 Pundit 没有选项,要传递 session 或其他参数,除了 current_user 并检查 entity,您可以改用 Rails.cache

# 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

要让 Devise 缓存当前角色,您需要覆盖 Devise 的 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

我创建了这个 demo rails application, you can play with it: see my solution variant with Rails.cache in rails_cache_solution 分支或在拉取请求中。

另请参阅这些文件以获取更多详细信息:

  • app/controllers/users/sessions_controller.rb
  • spec/controllers/posts_controller_spec.rb
  • app/policies/post_policy.rb
  • app/models/user.rb
  • README.md