views:

150

answers:

2

I've never really delved into the amazing cache techniques Rails provides until now. One thing that I really can't wrap my head around is how to resolve a this particular problem.

Given that I have a Blog model with many Posts:

class Blog < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  named_scope :published, :conditions => ["published_at < ?", Time.now]
end

And the show action in the BlogsController shows a list of Posts that have been published:

// BlogsController

def show
 @blog = Blog.find(params[:id)
end

// View

<% @blog.posts.published.each do |p| %>
 <h2><%=h p.title %></h2>
 <%= simple_format(p.content) %>
<% end %>

The cache has to expire when any change is done to the published_at attribute BUT it also need to do it when published_at is put in the future and that time is reached.

Can you guys throw me some ideas and pointers of how to best solve this? Cron-job or am I loosing my mind?

+4  A: 

The code you show doesn't use any of Rails' caching features. However your :published named scope will use (and, in production, remember through class caching) Time.now when that code is first executed.

I suspect you want this instead:

named_scope :published, lambda { { :conditions => ["published_at < ?", Time.now] } }

The lambda ensures that Rails re-evaluates your condition every time.

Andy Stewart
Yes Andy you're right about the 'lambda' way, but the code doesn't use any cache because I'm not using any yet since I'm not sure what approach to take, which was what the question is about.
The Tailor
+1  A: 

It all depends on the kind of data store you're using to store the cache.

If you're using the filesystem you could write a cron job to invalidate the cache at a specific interval, or encode the datetime that the cache is valid until in the cachekey and check that on every request and invalidate when necessary.

Alternatively if you're backend if memcached you can use an expirable cache, which is probably the best solution.

jonnii
Thanks, jonnii - I think this is what I was looking for.
The Tailor