Issues related to using doll caching in Russian with template inheritance

I used both template inheritance and Russian doll caching (using cache_digests gem ) independently of each other in separate parts of rather complicated Rails with great success.

I have difficulty using the two technologies together, reasonably, which makes me suspect that I might be doing something wrong ...

For a very simple example, consider an application consisting of two controllers ThingOnes and ThingTwos. This application has one layout ( layouts/application.html.erb ) that simply displays the header file: <%= render 'header' %> .

By default, Rails will look at a bunch of locations for this partial, including the view directory for the layout ( views/application/_header.html.erb ), as well as any specific for the current controller (e.g. views/thing_ones/_header.html.erb or views/thing_twos/_header.html.erb ). This means that for caching purposes, I basically have a list of template dependencies (not counting engines or something else):

 [ "application/header", "thing_ones/header", "thing_twos/header" ] 

Now we finish this rendering with caching, for example:

 <% cache 'header' do %> <%= render 'header' %> <% end %> 

Unfortunately, running rake cache_digests:nested_dependencies TEMPLATE=layouts/application leads to the following list of dependencies.

 [ "layouts/header" ] 

Template inheritance doesn't care at all. Modification of files not included in the list has the expected effect of changing files not included in the list - the cache did not expire properly and an outdated header is displayed.

This can be easily restored by specifying the appropriate template paths, for example:

 <% cache 'header' do %> <%# Template Dependency: application/header %> <%# Template Dependency: thing_ones/header %> <%# Template Dependency: thing_twos/header %> <%= render 'header' %> <% end %> 

This is really a very bad solution, since it does not grow well and requires a lot of frivolous design for caching calls in order to preserve the existing template inheritance behavior.

Similarly, you can more clearly indicate the location of the header, for example:

 <% cache 'header' do %> <%= render 'application/header' %> <% end %> 

It also does not allow us to preserve the existing template inheritance behavior, making it unusable for our needs.

The final option is to move the cache call to the partial parts of the header. This is not only inefficient, as it issues a render call from the cache. It is also more WET (write everything twice) than DRY, which is a big disconnect.

So, to get to my actual question (s) ... Am I doing this right? This seems like a pretty serious flaw that will affect a wide range of implementations, but I can't find a lot of discussion related to this particular problem, so I wonder if other actions make it work better. Is there a better way to do this, or at least automatically specify the entire hierarchy of template dependencies for partial renders?

+4
source share
1 answer

The problem is what you ultimately offer yourself: you need to move the cache method into your rendered templates.

This may seem like a lot of code, but it is necessary for the cache to work correctly. Also, if your partial ( _header.html.erb in the application, thing_ones and thing_twos) are different, should the cache key be different. This means you should get something like this:

 # layouts/application.html.erb <%= render 'header' %> # application/_header.html.erb <% cache 'application_header' do %> ... <% end %> # thing_ones/_header.html.erb <% cache 'thing_ones_header' do %> ... <% end %> # and thing_twos/_header.html.erb <% cache 'thing_twos_header' do %> ... <% end %> 

Without different cache keys, these caches override each other, which, for example, if. application/_header.html.erb was cached first, then it will be the one displayed on the ThingOnes and ThingTwos .

+1
source

Source: https://habr.com/ru/post/1208296/


All Articles