Caching strategies in rails 4

24
Key-based cache expiration in Rails 4 ...or Rails 3 with a dependency Wednesday, July 31, 13

Transcript of Caching strategies in rails 4

Page 1: Caching strategies in rails 4

Key-based cache expiration in

Rails 4...or Rails 3 with a dependency

Wednesday, July 31, 13

Page 2: Caching strategies in rails 4

Building Blocks (ActiveRecord::Base)

@product.cache_key

=> “products/1281-20130717091609”

“#{name}/#{id}-#{timestamp}”

Wednesday, July 31, 13

Page 3: Caching strategies in rails 4

Building Blocks (ActionView::Helpers::CacheHelper)

- cache @product do %h1= @product.name = image_tag @product.image.url

Wednesday, July 31, 13

Page 4: Caching strategies in rails 4

Write fragment views/products/1-20130728191246157664000

(“views/#{cache_key}”)

- cache @product do %h1= @product.name = image_tag @product.image.url

Wednesday, July 31, 13

Page 5: Caching strategies in rails 4

You can compose fragment keys, too...

- cache [@product, “reviews”] do %h1= @product.name = image_tag @product.image.url

Write fragment views/products/1-20130728191246157664000/reviews

“views/#{cache_key}/#{extra_args.join(‘/’)}”

Wednesday, July 31, 13

Page 6: Caching strategies in rails 4

“But what if I change a template?”

Wednesday, July 31, 13

Page 7: Caching strategies in rails 4

Rails.cache.clear

Wednesday, July 31, 13

Page 8: Caching strategies in rails 4

“But what if I deploy 5 times a day”

Wednesday, July 31, 13

Page 9: Caching strategies in rails 4

sucks

Wednesday, July 31, 13

Page 10: Caching strategies in rails 4

Just kidding!™

Wednesday, July 31, 13

Page 11: Caching strategies in rails 4

# Gemfile

gem ‘pg’

gem ‘cache_digests’

gem ‘haml-rails’

gem ‘cancan’

# ...

(Rails 3 only – built into actionpack 4)

Wednesday, July 31, 13

Page 12: Caching strategies in rails 4

Write fragment views/products/1-20130728191246157664000/3b2b93d56d331aa7a1bf9267a656d3c9

(“views/#{cache_key}/#{template_digest}”)

- cache @product do %h1= @product.name = image_tag @product.image.url

With cache_digests...

note: template_digest is a digest of the current template and all of it’s dependencies (more on that later)Wednesday, July 31, 13

Page 13: Caching strategies in rails 4

Cache digest for products/_product.html: 42eb891316f21e68798de5d5aa8021d5

Read fragment views/products/1-20130728191246157664000/42eb891316f21e68798de5d5aa8021d5

Write fragment views/products/1-20130728191246157664000/42eb891316f21e68798de5d5aa8021d5

- cache @product do %h1= @product.name - # image_tag @product.image.url

...change the template

Wednesday, July 31, 13

Page 14: Caching strategies in rails 4

template change-> new digest

-> new fragment key-> busted cache!

Wednesday, July 31, 13

Page 15: Caching strategies in rails 4

And we didn’t have to do anything!

Wednesday, July 31, 13

Page 16: Caching strategies in rails 4

“Russian doll” caching strategythe notorious

Wednesday, July 31, 13

Page 17: Caching strategies in rails 4

class Product < ActiveRecord::Base has_many :reviewsend

class Review < ActiveRecord::Base belongs_to :product, touch: trueend

Product’s cache key now dependent on its reviews

Wednesday, July 31, 13

Page 18: Caching strategies in rails 4

@review.update!(rating: 3)

@review.product’s key gets bumped as well

Wednesday, July 31, 13

Page 19: Caching strategies in rails 4

the “russian doll”...

# products/index.haml

- cache [@products.order(“updated_at ASC”).last, “index”] do%ul.products

- @products.each do |product| = render product

# products/_product.haml

- cache product do %li.product %h1= product.name %h2 Reviews! %ul.reviews - product.reviews.each do |review| = render review

# reviews/_review.haml

- cache review do %li.review %h4= “#{review.rating} stars!” %p.content= review.content

Wednesday, July 31, 13

Page 20: Caching strategies in rails 4

the “russian doll”...index

product

reviews list

review

review

review

Wednesday, July 31, 13

Page 21: Caching strategies in rails 4

@product.reviews.last.update!(rating: 5)

Last review will get re-rendered (and cached) and container (review list) will get busted -

but when list re-renders all but this last review can be fetched from cache.

Wednesday, July 31, 13

Page 22: Caching strategies in rails 4

View the template dependency tree...

$ rake cache_digests:nested_dependencies TEMPLATE=your/template/name

ex:

and rake task for Rails 4: https://gist.github.com/nzaillian/6127613

Wednesday, July 31, 13

Page 23: Caching strategies in rails 4

Explicit dependencyIf Rails just can’t seem to figure out your dependency you can declare an explicit dependency in a template by including a comment with a special form:

- # Template Dependency: reviews/summary

(...but you shouldn’t ever have to do this)

Wednesday, July 31, 13

Page 24: Caching strategies in rails 4

Other Resourceshttps://github.com/rails/cache_digests

http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works

http://www.youtube.com/watch?v=yhseQP52yIY&t=0:39:39

must watch! (DHH’s Railsconf 2013 outline of key-based caching)

http://api.rubyonrails.org/classes/ActionView/Helpers/CacheHelper.html

Wednesday, July 31, 13