6
select * from Foo where id = 200

How to cache finding object by id, since we observe a select call being made all the time on a certain id. How should we enable this in rails in a non obtrusive fashion, so that we can switch between any cache store in the future (say memcached or redis)

EDIT:

Much similar to Hibernate based caching strategy org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE which is applied on all Entity classes in Java EE.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Joe
  • 14,513
  • 28
  • 82
  • 144
  • 2
    Rails' approach to caching is a bit different to Hibernate's. You might want to take a look at http://guides.rubyonrails.org/caching_with_rails.html and http://broadcastingadam.com/2012/07/advanced_caching_revised/ for some good overviews on how it all works. My understanding of your question is that you want to avoid having to grab an object from the database on each request - is that right? It may help if you post some more code. – Alex Ghiculescu Mar 16 '13 at 15:09
  • As Alex says, not really enough information here. What is this select-by-id? Where does it come from? From calling Hibernate get/load? Is this Hibernate at all? Or ruby-on-rails? – Steve Ebersole Mar 16 '13 at 16:16
  • @AlexGhiculescu I don't want to grab an object from the database on each request from the same id. – Joe Mar 16 '13 at 17:22
  • @SteveEbersole I would like to know if ruby-on-rails has something similar to the caching strategy in hibernate. – Joe Mar 16 '13 at 17:22

4 Answers4

3

In your Foo model you probably want something like this

class Foo < ActiveRecord::Base

  def self.find_some_foo(foo_id)
    Rails.cache.fetch("foo_#{foo_id}", expires_in: 7.days) do
      begin
        self.where(:id => foo_id)
      rescue Exception => e
        logger.info "Exception fetching Foo ID: #{e.to_s}"
        nil
      end
    end
  end

end

Set up your application’s default cache store by calling config.cache_store= inside your config/application.rb file, for example, config.cache_store = :memory_store The link Alex Ghiculescu provided link has good information in section 2.1.

The rails cache store is automatically populated when you try to fetch a key that doesn't exist in the cache_store. For this reason, it's important to come up with a good naming convention for your keys. Once you have the basics established, it's easy to switch between different cache stores by making the appropriate change in config/application.rb. Some of the choices are memory store, file store, memcache, or any combination of cache stores.

To flush the rails in-memory cache restart your rails server. To flush the file cache, type rake tmp:clear. To flush memcache, see this link.

Community
  • 1
  • 1
Gui LeFlea
  • 795
  • 3
  • 12
2

You can simple use rails's built-in caching

Rails.cache.fetch :cache_id_here, :expires_in => 1.days do
   Model.find(id)
end

Change :cache_id_here with whatever you want and set the expiration to your preferences. You can use this caching with memcached or whatever alternative cache store you want. You simply set that in your application config.

UPDATE

I'm working on a gem that solves this problem by extending Rail's .find and .save methods and caching results. It's super beta and hasn't been tested in production yet but if you're willing to try it out, take a look at the repo: https://github.com/johnkoht/cache-money-millionaire and let me know your thoughts.

Essentially if you call Post.find(3) then it will automatically find and create a cached version with a cache key of Post 3 which will automatically be updated on save or touch. Like I said, it's beta but it solves the issue.

johnkoht
  • 602
  • 6
  • 11
1

Following gems provide write-through cache features:

record-cache

Supports Rails 3. Actively developed.

cache_money

Built by Twitter, now maintained by the community. I dont know if it supports Rails 3.

Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
0

Identity Map could help: http://api.rubyonrails.org/classes/ActiveRecord/IdentityMap.html

Its still in beta tho, so use with care. It will also not track associations.

Sascha Kaestle
  • 1,293
  • 12
  • 15