我正在开发一个具有默认范围
的用户模型的应用程序default_scope { preload(:preference, :permission, :user_detail, :log) }
每次我们调用current_user都会触发4个查询
对于current_user
,我已经超越了设计
module DeviseOverrides
def self.included(base)
base.class_eval {
alias_method :devise_current_user, :current_user
helper_method :current_user, :user_signed_in?
}
base.send(:include, InstanceMethods)
end
module InstanceMethods
def current_user
@current_user ||= warden.try(:user) || anonymous_user
end
def user_signed_in?
warden.user.present?
end
end
end
假设我们在一个页面上有5个模块。并加载我们触发ajax调用的每个模块。基本上,我们会发出5个请求。现在,对于每5个请求,@ current_user首次为nil,它将触发查询。同样,当我们在同一请求中调用current_user时,它将从缓存中返回。
我想要的是第一个请求,它将触发查询并将其存储在@current_user
中。稍后,对于页面中的所有其他请求,它应从缓存中返回而不是触发查询
@current_user ||= warden.try(:user) || anonymous_user
warden.user.present?
有人可以指导我我需要做什么
class ApplicationController < ActionController::Base
around_action :set_current_user
def set_current_user
User.current = current_user
yield
ensure
User.current = nil
end
end
class User < ApplicationRecord
default_scope { preload(:preference, :permission, :user_detail, :log)
def self.current=(user)
Thread.current[:current_user] = user
end
def self.current
Thread.current[:current_user]
end
end
按照@kgilpin的建议,我更新了application_controller方法
def set_current_user
User.current = warden.try(:user) || anonymous_user
yield
ensure
User.current = nil
end
答案 0 :(得分:1)
您可以初始化当前用户并将其存储在线程局部变量中,然后在过程中的任何位置访问它。
例如,您的ApplicationController
会执行以下操作:
around_action :with_current_user
protected
def with_current_user
Thread.current[:current_user] = warden.try(:user) || anonymous_user
begin
yield
ensure
Thread.current[:current_user] = nil
end
end
end
Thread.current[:current_user]
现在是Ruby进程相同线程/纤维中任何地方的当前用户。
请注意,Ruby线程本地存储语法[], []=
也可以安全地用于光纤。参见https://docs.ruby-lang.org/en/2.6.0/Thread.html#method-i-5B-5D-3D。
答案 1 :(得分:0)
include不可能做到,因为include模块的每个实例都有自己的@current_user。
您需要使用依赖关系注入或动态依赖关系解析机制在所有对象都可以访问它的范围内设置@current_user变量。
一个例子:
class CurrentUserHolder
include Singleton
attr_accessor :current_user
end
module InstanceMethods
def current_user
CurrentUserHolder.instance.current_user ||= warden.try(:user) || anonymous_user
end
end