Reputation: 4538
I'd like the same cached fragment to be used by several actions. I have this in three views:
- cache( 'categories_tree' ) do
.categories-tree
- if 'helper' == categories_tree_type
= raw categories_tree @categories
- elsif 'partial' == categories_tree_type
= render 'categories/tree', :categories => @categories
but it results in three caches:
piousbox@piousbox-samsung:~/projects/bjjcollective$ tree tmp
tmp
├── cache
│ ├── 2D6
│ │ └── 121
│ │ └── views%2Fcategories_tree%2F3e567c5c7f95eb7a8ccee13e8ba37676
│ ├── 35A
│ │ └── 2F1
│ │ └── views%2Fcategories_tree%2F594ceedfd2b2c5decf4ee905f40a97c5
│ └── 377
│ └── 2F1
│ └── views%2Fcategories_tree%2Fe6d3b9cc3ceea0b8ae33ebffe3006e90
├── pids
│ └── server.pid
├── sessions
└── sockets
How would I make three views share the same cached fragment? I moved them all to the same controller but it didn't help.
Upvotes: 1
Views: 171
Reputation: 18682
If you URL decode the cache keys Rails uses, you can see which parts they're composed of:
views/categories_tree/3e567c5c7f95eb7a8ccee13e8ba37676
views/categories_tree/594ceedfd2b2c5decf4ee905f40a97c5
views/categories_tree/e6d3b9cc3ceea0b8ae33ebffe3006e90
It includes the categories_tree
key you specified.
But Rails by default also includes an MD5 hash of the view file and its dependencies (other views rendered from the view). It does this so that if you change the view or one of its dependent views, the cache key changes and caches are regenerated to make sure the changes in the view are shown.
You can solve this problem in two ways, simply pick your favourite. Note that below I have assumed that @categories
will always have the same contents, as suggested by your question. If this is not the case you'd need to include it in your cache key to make sure the correct tree is shown.
You can tell Rails to not generate that MD5 digest. Then the cache key will be the same for all three partials and there will be only one fragment in the cache.
Simply do this:
- cache('categories_tree', skip_digest: true) do
I would discourage this approach, as it will remove the benefit of caches being automatically busted on a change in the views. If you use this approach, you have to be sure to change the cache key every time you make a change.
You've repeated the code several times in different views, so it would make sense for it to be extracted into its own partial:
# app/views/application/categories_tree
- cache('categories_tree') do
.categories-tree
- if 'helper' == categories_tree_type
= raw categories_tree categories
- elsif 'partial' == categories_tree_type
= render 'categories/tree', :categories => categories
Then, render the partial in the view templates that use it:
= render('categories_tree', categories: @categories)
Its cache digest will now be the same and the same fragment will be reused by the cache. You'll still benefit from the automatic cache busting this way.
You can read more on caching in the Rails documentation.
Upvotes: 1