Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 基于多请求的缓存查询_Ruby On Rails_Ruby_Devise_Ruby On Rails 5.2 - Fatal编程技术网

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
return
user.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