Antony Sastre
Antony Sastre

Reputation: 617

Page Caching, best practice on automatic expires/sweepers

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?

Upvotes: 2

Views: 572

Answers (2)

jonnii
jonnii

Reputation: 28332

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.

Upvotes: 1

Andy Stewart
Andy Stewart

Reputation: 5498

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.

Upvotes: 5

Related Questions