#90 Fragment Caching (revised)
Feb 18, 2012 | 9 minutes | Performance, Views, Caching
If you need to cache a certain section of a page instead of the entire page, fragment caching is the way to go. Learn how caching is stored, how to create auto expiring caches, and more.
- source codeProject Files in Zip (101 KB)
- mp4Full Size H.264 Video (22.1 MB)
- m4vSmaller H.264 Video (11.6 MB)
- webmFull Size VP8 Video (14.3 MB)
- ogvFull Size Theora Video (29.8 MB)
A related blog post by 37Signals on this technique: http://37signals.com/svn/posts/3112-how-basecamp-next-got-to-be-so-damn-fast-without-using-much-client-side-ui
I thought to this article as soon as the episode started! =)
What's a good way to auto-expire the "recent_articles" fragment you have there? Would something like this work?
A quick test in the console suggests that this should work (although you probably won't want to do this when you have a lot of objects in you array?)
You could use something like Article.maximum(:updated_at) as a cache key to make it shorter.
Good point. (This will most likely result in a different SQL query due to lazy/last-minute evaluation in AR, probably for the better...)
I think the main problem with this approach is that you have to load and use all the recent article models, even when you read from the cache.
If you already have the article models loaded just to build the name of the cache, you might as well just print the link_to entries and skip the cache altogether. I would think the main benefit of caching this section of the page would be to avoid the SQL call that loads the recent article models in the first place.
Apparently the DB queries is not the bottleneck for most cases, if you can avoid complex joints, etc... This came as a surprise to me too. (See the linked 37Signals article and the comments)
I saw that - great read! Makes sense.
To completely get rid of the SQL queries issue, you can use staugaard's wonderful kasket gem (that Zendesk also uses, so, you know, probably okay for production :D)
Does it make sense to nest cache resources this way? Is it Rails so slow to render a template that you should waste more cache memory?
Well, there's also the fact that server rendering is holding up a blocking request. Time/throughput is more expensive than memory.
check out this http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works Sofia Cardita of 37 signals does a great job explaining caching
Post is by DHH, the name you mention is from a comment. ;-)
Hi i have a strange issue with fragment caching with rails 3.2 & memcached as a cache store.
I use framgent caching in a partial and loop on a instance variable @recent_posts in my index view.
The problem, i think, is in my index action.
I didn't change anything to my code, so normally,my partial should be cached but the sql request that get my @recent_post should be processed.
Or it appears that the first request trigger the sql but the requests after wont.
To be a little more precise, my @recent_posts is defined by something like that.
@recent_post = SomeModel.first.get_last_posts.
And it appear that the SomeModel.first call is triggered every time but only the .get_last_post sql request won't be processed for the 2+ request...
Any though ?
So in fact it seems that i just learned something.
If i create an instance variable in my action
@last_posts = User.first.get_last_posts
but doesn't use this variable nowhere else in my action or view
then only the User.first call will be triggered to get the user so i can retrieve his last posts.
Then the user.get_last_posts call won't be triggered because the result of this request is never used in the rest off my app.
So, to be clear, when i define an instance variable, the object is keep in cache, and if it's needed later in the controller/view code, then the method associated i.e get_last _post is processed
am i right ?
Should i go see a railcast which perfectly explain this behavior ? :)
and the answer
see lazy query
Advanced Caching in Rails ... I'll just leave this here.
for the touch => true property in the association, is it possible to chain these together?
class Article < ActiveRecord::Base
class Post < ActiveRecord::Base
belongs_to :posts, :touch => true
class Comment < ActiveRecord::Base
belongs_to :posts, :touch => true
in the above, if I do:
will that touch the associated post AND article? (and therefore trigger a refresh on articles?)
hi, is there any way to encrypt on the way out / decrypt on the way in? i have sensitive info in my app that i'd like to ensure remains inaccessible to anyone who may connect to my memcache server.
def sweep not working for me.
Just had to add: ActionController::Base.new.expire_fragment
If anybody else wants to use caching in their decorators / presenters and use HAML, then this is how to do it:
Heres a blog discussing implementation in rails 4 http://www.charliemassry.com/posts/52-caching-rails-views
Any best practices about how to test Fragment Caching?