Eqbal
Eqbal

Reputation: 1879

Caching with Instance Variable in ruby with expired_after like feature

I'm developing a ruby application ( not a rails one ), I'm looking for a very simple way to cache some of the frequently used results. as for example :

 @users ||= User.all

Now this is working perfectly but I'm looking for a way to add something like expire option that will refresh the command each period of time . in other words I need the same action to be performed in each slice of time or after a number of times . I remember that in rails I used to run memcached and use something like :expire or :expired_at .

Any help would be highly appreciated .

Upvotes: 1

Views: 964

Answers (2)

Eqbal
Eqbal

Reputation: 1879

Don't u think the above one is a little bit complicated ?

I was trying something like :

Cache ={}
def fetch(key, ttl)
  obj, timestamp = Cache[key.to_sym]
  if obj.nil? || Time.now - timestamp > ttl
    obj = yield
    Cache[key]=[obj, now]
  end 
  obj
end

I would love to hear your comment about this one

Upvotes: 1

Alex D
Alex D

Reputation: 30445

How about something like:

class Class
  # create a method whose return value will be cached for "cache_for" seconds
  def cached_method(method,cache_for,&body)
    define_method("__#{method}__".to_sym) do |*a,&b|
      body.call(*a,&b)
    end
    class_eval(<<METHOD)
      def #{method}(*a,&b)
        unless @#{method}_cache && (@#{method}_expiry > Time.now)
          @#{method}_cache  = __#{method}__(*a,&b)
          @#{method}_expiry = Time.now + #{cache_for}
        end
        @#{method}_cache
      end
METHOD
  end
end

You can use it like:

class MyClass
  cached_method(:users,60) do
    User.all
  end
end

This will cache the users for 60 seconds. If you call users again on the same object after 60 or more seconds pass, it will execute the method body again and update the cache.

Upvotes: 1

Related Questions