lapinkoira
lapinkoira

Reputation: 8978

Rails low level query caching

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

Answers (1)

Alex
Alex

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

Related Questions