Is there a way to cache per-request data in 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. Is there a hash where I can store and access such data?
It needs to be fairly global and accessible from views, controllers, and libs, like Rails.cache and I18n are.
I'm ok doing some monkey-patching if that's what it takes.
There is also the request_store gem. From the documentation:
Add this line to your application's 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 . I stole the design from the SQL Query Cache.
Configure it up in config/environment.rb
with:
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. It uses Thread.current
to store your data, and takes care of cleaning up the data after each request.
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.
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:
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? It uses Session but is automatically cleared.
According to this railscast it's stored per request.
app/models/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). 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:
MyCacher.result
This will cache the expensive action for the duration of a request.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.