Reputation: 8978
I would like to cache a controller query result because it's a very static data which wont change very often.
So I am wondering if I can just define this method:
def cached_collections
Rails.cache.fetch('collections', :expires_in => 24.hours) do
Collection.all
end
end
And in some way instead using
@collections = Collection.all
can I just call the method?
@collections = cached_collections
This is working but it's the right way to do it? before using Memcached or Redis
Upvotes: 0
Views: 547
Reputation: 2518
In your method cached_collections
you are trying to cache a complex object structure (an instance of ActiveRecord::Relation
). This is probably achievable, but a much easier approach is to just cache your views or view fragments:
<% cache do %>
<% @collection.each do |item| %>
<%# do something with item %>
<% end %>
<% end %>
You can still initialize your queries inside of your controller, e.g.:
@collection = Collection.limit(10)
Instances of ActiveRecord::Relation
are lazy; they mimic the behavior of an array in a way, that they won't hit the database until you explicitly access the fetched result, e.g: @collection.first
or @collection.each{ #... }
So no database query as long as your fragments are cached.
Refer to this for caching examples: http://guides.rubyonrails.org/caching_with_rails.html
Edit:
For JSON requests, you could do it like this:
@collection = Collection.all
render :json => Rails.cache.fetch('collections', :expires_in => 24.hours) do
@collection.to_json
end
Again, no request to the database unless your cache is stale and no complex object structure in your cache.
Upvotes: 4