Ruby on rails 基于多请求的缓存查询
我正在开发一个应用程序,其中我有一个用户模型,该模型具有默认范围Ruby on rails 基于多请求的缓存查询,ruby-on-rails,ruby,devise,ruby-on-rails-5.2,Ruby On Rails,Ruby,Devise,Ruby On Rails 5.2,我正在开发一个应用程序,其中我有一个用户模型,该模型具有默认范围 default_scope { preload(:preference, :permission, :user_detail, :log) } 每次调用当前用户时,它都会触发4个查询 对于当前用户,我已覆盖该装置 module DeviseOverrides def self.included(base) base.class_eval { alias_method :devise_current_use
default_scope { preload(:preference, :permission, :user_detail, :log) }
每次调用当前用户时,它都会触发4个查询
对于当前用户
,我已覆盖该装置
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_用户第一次将为零,它将触发一个查询。同样,当我们在同一请求中调用当前_用户时,它将从缓存返回
我想要的是,对于第一个请求,它应该触发查询并存储在@current\u 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
对于include,您试图做的是不可能的,因为include模块的每个实例都有自己的@current_用户 您需要使用依赖项注入或动态依赖项解析机制,在所有对象都可以访问的范围内设置@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
您可以初始化当前用户并将其存储在线程局部变量中,然后从进程中的任何位置访问它 例如,您的
应用程序控制器将执行以下操作:
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线程本地存储语法[],[]=
也可以安全地与光纤一起使用。请参阅。我现在如何调用与以前相同的当前用户方法。或者您可以调用CurrentUserHolder.instance.current\u user
。请注意,在直接呼叫时,由于之前未设置InstanceMethods模块,因此可能为零。我将如何包括InstanceMethods模块?对于整个应用程序而言,当前的全局用户似乎不正确。这是op要求的;P我会使用一些依赖注入机制,但在系统的给定背景下,不可能给出一个代码片段。我的应用程序控制器中已经有了相同的代码。我已经在我的问题中更新了相同的方法,所以现在不应该更新你的设备overrides::InstanceMethods.current_user
returnuser.current_user
?我根据你建议的更改更新了我的方法。我还有一个疑问。我也有一个用户登录了?在designe_覆盖模块中,它再次触发4个查询。我怎样才能避免呢?
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