#93
Feb 17, 2008

Action Caching

Action caching behaves much like page caching except it processes the controller filters. You can also make it conditional as seen in this episode.
Download (19.8 MB, 7:04)
alternative download for iPod & Apple TV (11.2 MB, 7:04)

Resources

# products_controller.rb
cache_sweeper :product_sweeper, :only => [:create, :update, :destroy]
caches_action :index, :cache_path => :index_cache_path.to_proc

#...

private

def index_cache_path
  if admin?
    '/admin/products'
  else
    '/public/products'
  end
end

# config/environments/development.rb
config.action_controller.perform_caching = true

# config/environment.rb
config.load_paths << "#{RAILS_ROOT}/app/sweepers"

# app/sweepers/product_sweeper.rb
class ProductSweeper < ActionController::Caching::Sweeper
  observe Product
  
  def after_save(product)
    expire_cache(product)
  end
  
  def after_destroy(product)
    expire_cache(product)
  end
  
  def expire_cache(product)
    expire_action '/admin/products'
    expire_action '/public/products'
  end
end

RSS Feed for Episode Comments 12 comments

1. Brad Gessler Feb 17, 2008 at 23:44

Got a link to that caching plugin you were talking about?


2. Ted Feb 18, 2008 at 07:11

Hey Ryan, I'm wondering if it could have been a little more clever and used string replacement like this:

caches_action :index, :cache_path => Proc.new{ "/products/#{admin?}" }

That would put the cache files as "/products/true" and "/products/false". Granted not the best of names, but what do we care what the cache files are named under the hood? ;-)


3. Andrew Kaspick Feb 18, 2008 at 08:41

I have a plugin called conditional caching that I wrote years ago, and is still maintained.

http://agilewebdevelopment.com/plugins/conditional_caching

Although after seeing this railscast, there are some features (:cache_path) that didn't exist when I first wrote it, so I think I'll be making another update of the plugin soon to make use of it. :)


4. Mitchell Blankenship Feb 19, 2008 at 13:31

First off Ryan thank you so much for all your railscasts. They have been invaluable in my learning process. Now I'm wondering if action caching will work with pagination. I tried a couple of different things but I can't seem to get it to work. I was just wondering before I go to a lot of recoding on my existing blog to add this.


5. Andrew Kaspick Feb 19, 2008 at 17:40

I notice that :cache_path removes the name of the host if a string is returned.

Without :cache_path the fragment may be called "localhost:3000/foobar", but if you specify :cache_path => "/foobar", the fragment is written as just "/foobar" without the host which is a big difference.

Using the to_proc technique explained here returning a string is basically the same as using just a string, so you'll lose the hostname in the fragement as well.

So if you depend on the host in the written fragment, you'll have to include the hostname in your string.


6. Ryan Bates Feb 24, 2008 at 22:43

Sorry for the delayed response everyone.

@Brad, the plugin I was referring to is called Action Cache. However I'm not entirely sure if it works with Rails 2.0, there are alternative solutions as Andrew mentioned.
http://wiki.rubyonrails.org/rails/pages/Action+Cache+Update+Plugin

@Ted, yep, that should work. I prefer the more descriptive names but to each his own. :)

@Mitchell, in order to get this to work with pagination you'll need to include the page number in the name of the cache. You can use the dynamic technique as shown at the end of this episode to put the params[:page] value in the name of the cache and it should work.

@Andrew, you're right, the domain name gets chopped when passing a string as the path. This behaves the same in fragment caching as well. I can see how either behavior could be desirable. If you do want the domain with the port in the path then you can include that in the string.


7. Wallen Feb 28, 2008 at 06:53

Excellent tutorial! I did not feel cheated ;).

Why bother caching the admin page? Is it not possible to cache_action :if ?


8. Ryan Bates Feb 28, 2008 at 08:52

@Wallen, as far as I know there's no "if" option. So if you want to disable caching entirely you should look into a plugin as mentioned above. Actually, I've never tried returning nil for the cache path so that might work too.


9. Mislav Mar 16, 2008 at 09:17

Great episode! I liked the twist :)


10. Dave Mar 21, 2008 at 11:33

Ryan, thanks for the great screencasts. Does the :cache_path work for Rails 1.2.6? My proc never seems to get called.


11. Amos King Apr 04, 2008 at 15:20

I am caching a lot of actions and some with ids. I was caching them under different folders. My get path uses this string to return:

"/#{params[:controller]/params[:action]"

There is another version with the id tacked on. But expire_action is not removing any of the caches. My call in foo_sweeper looks like this.

expire_action "/foo"

any ideas?

Thanks


12. kino May 23, 2008 at 01:53

I now shift the weight of transcendental evidence of transcendental phenomenology from the ego to experiences.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player