简体   繁体   English

Rails 每个请求 hash?

[英]Rails per-request hash?

Is there a way to cache per-request data in Rails?有没有办法在 Rails 中缓存每个请求的数据? For a given Rails/mongrel request I have the result of a semi-expensive operation that I'd like to access several times later in that request.对于给定的 Rails/mongrel 请求,我有一个半昂贵的操作的结果,我想稍后在该请求中访问几次。 Is there a hash where I can store and access such data?是否有 hash 可以在其中存储和访问此类数据?

It needs to be fairly global and accessible from views, controllers, and libs, like Rails.cache and I18n are.它需要是相当全局的,并且可以从视图、控制器和库中访问,就像 Rails.cache 和 I18n 一样。

I'm ok doing some monkey-patching if that's what it takes.如果需要的话,我可以做一些猴子修补。

  • Memcached doesn't work because it'll be shared across requests, which I don't want. Memcached 不起作用,因为它将在请求之间共享,这是我不想要的。
  • A global variable similarly doesn't work because different requests would share the same data, which isn't what I want.全局变量同样不起作用,因为不同的请求将共享相同的数据,这不是我想要的。
  • Instance variables don't work because I want to access the data from inside different classes.实例变量不起作用,因为我想从不同的类中访问数据。

There is also the request_store gem.还有request_store gem。 From the documentation:从文档中:

Add this line to your application's Gemfile:将此行添加到应用程序的 Gemfile:

gem 'request_store'

and use this code to store and retrieve data (confined to the request):并使用此代码存储和检索数据(仅限于请求):

# Set
RequestStore.store[:foo] = 0

# Get
RequestStore.store[:foo]

Try PerRequestCache .尝试PerRequestCache I stole the design from the SQL Query Cache.我从 SQL 查询缓存中窃取了设计。

Configure it up in config/environment.rb with:config/environment.rb中配置它:

config.middleware.use PerRequestCache

then use it with:然后使用它:

PerRequestCache.fetch(:foo_cache){ some_expensive_foo }

One of the most popular options is to use the request_store gem, which allows you to access a global store that you from any part of your code.最受欢迎的选项之一是使用request_store gem,它允许您从代码的任何部分访问全局存储。 It uses Thread.current to store your data, and takes care of cleaning up the data after each request.它使用Thread.current来存储您的数据,并负责在每次请求后清理数据。

RequestStore[:items] = []

Be aware though, since it uses Thread.current , it won't work properly in a multi-threaded environment where you have more than one thread per request.但请注意,由于它使用Thread.current ,因此它无法在每个请求有多个线程的多线程环境中正常工作。

To circumvent this problem, I have implemented a store that can be shared between threads for the same request.为了规避这个问题,我实现了一个可以在同一请求的线程之间共享的存储。 It's called request_store_rails , it's thread-safe, and the usage is very similar:它被称为request_store_rails ,它是线程安全的,用法非常相似:

RequestLocals[:items] = []

Global variables are evil.全局变量是邪恶的。 Work out how to cleanly pass the data you want to where you want to use it.弄清楚如何干净地将您想要的数据传递到您想要使用它的地方。

Have you considered flash?你考虑过flash吗? It uses Session but is automatically cleared.它使用 Session 但会自动清除。

Memoisation ? 记忆

According to this railscast it's stored per request.根据this railscast ,它是按请求存储的。

app/models/my_cacher.rb应用程序/模型/my_cacher.rb

class MyCacher
  def self.result
    @@result ||= begin
      # do expensive stuff
      # and cache in @@result
    end
  end
end

The ||= syntax basically means "do the following if @@result is nil" (ie not set to anything yet). ||= 语法基本上意味着“如果@@result 为nil,则执行以下操作”(即尚未设置为任何内容)。 Just make sure the last line in the begin/end block is returning the result.只需确保开始/结束块中的最后一行返回结果即可。

Then in your views/models/whatever you would just reference the function when you need it:然后在您的视图/模型/任何您需要时引用 function 的内容:

MyCacher.result

This will cache the expensive action for the duration of a request.这将在请求期间缓存昂贵的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM