From c21cc877e089b623bbbbb6a3b582cf5a03984112 Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Tue, 28 Jul 2015 15:06:04 +0200 Subject: Add a "Managing dependencies" part to the caching guide [ci skip] --- guides/source/caching_with_rails.md | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'guides') diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md index 3d37b546a1..3836645b3f 100644 --- a/guides/source/caching_with_rails.md +++ b/guides/source/caching_with_rails.md @@ -152,6 +152,93 @@ With `touch` set to true, any action which changes `updated_at` for a game record will also change it for the associated product, thereby expiring the cache. +### Managing dependencies + +In order to correctly invalidate the cache, you need to properly define the +caching dependencies. Rails is clever enough to handle common cases so you don't +have to specify anything. However, sometimes, when you're dealing with custom +helpers for instance, you need to explicitly define them. + +#### Implicit dependencies + +Most template dependencies can be derived from calls to `render` in the template +itself. Here are some examples of render calls that `ActionView::Digestor` knows +how to decode: + +```ruby +render partial: "comments/comment", collection: commentable.comments +render "comments/comments" +render 'comments/comments' +render('comments/comments') + +render "header" => render("comments/header") + +render(@topic) => render("topics/topic") +render(topics) => render("topics/topic") +render(message.topics) => render("topics/topic") +``` + +On the other hand, some calls need to be changed to make caching work properly. +For instance, if you're passing a custom collection, you'll need to change: + +```ruby +render @project.documents.where(published: true) +``` + +to: + +```ruby +render partial: "documents/document", collection: @project.documents.where(published: true) +``` + +#### Explicit dependencies + +Sometimes you'll have template dependencies that can't be derived at all. This +is typically the case when rendering happens in helpers. Here's an example: + +```html+erb +<%= render_sortable_todolists @project.todolists %> +``` + +You'll need to use a special comment format to call those out: + +```html+erb +<%# Template Dependency: todolists/todolist %> +<%= render_sortable_todolists @project.todolists %> +``` + +In some cases, like a single table inheritance setup, you might have a bunch of +explicit dependencies. Instead of writing every template out, you can use a +wildcard to match any template in a directory: + +```html+erb +<%# Template Dependency: events/* %> +<%= render_categorizable_events @person.events %> +``` + +As for collection caching, if the partial template doesn't start with a clean +cache call, you can still benefit from collection caching by adding a special +comment format anywhere in the template, like: + +```html+erb +<%# Template Collection: notification %> +<% my_helper_that_calls_cache(some_arg, notification) do %> + <%= notification.name %> +<% end %> +``` + +#### External dependencies + +If you use a helper method, for example, inside a cached block and you then update +that helper, you'll have to bump the cache as well. It doesn't really matter how +you do it, but the md5 of the template file must change. One recommendation is to +simply be explicit in a comment, like: + +```html+erb +<%# Helper Dependency Updated: Jul 28, 2015 at 7pm %> +<%= some_helper_method(person) %> +``` + ### Low-Level Caching Sometimes you need to cache a particular value or query result instead of caching view fragments. Rails' caching mechanism works great for storing __any__ kind of information. -- cgit v1.2.3