cache_digests
cache_digests copied to clipboard
Fix lookup of templates with specific formats
Hi, I was playing around trying to use cache_digests to generate a checksum for a generated pdf (based on views with pdf as the format).
After much head-scratching I think I actually found a small bug in TemplateDigestor. There seems to be a missing argument in the call to ActionView::LookupContext which causes formats of templates to be ignored.
After this small change suddenly my digests started updating as I modified partial used by the pdf.
Can you add a test for this to prevent regression? And then submit a PR for rails/master as well. Thanks for finding this!
I am mostly an Rspec guy but I'll give it a shot.
The test did fail and changing the FixtureFinder made them all pass again. Do you think that is enough regression protection?
I am concerned that the problem of template lookup may be more subtle than I first expected. I have a very interesting failure case.
Before my patch
- digests would always be made of the some_view.html.erb even when another format was requested (e.g. some_view.pdf.erb)
- digests could be made of that template "at any time" (read on for clarification).
After my patch
- digests will be made of the requested format and dependencies tracked correctly.
- digests can no longer be generated after a render() has been performed. At least not always.
What do I mean: after render()
I am generating pdfs from a view (using Wicked PDF) and using the digest of the view tree to invalidate and re-render the pdf when required.
- a new ActionView object is created and rendered to a string
- the html string is given to Wicked PDF.
- When saving the pdf file a digest is generated based on the cache digest among other things.
This is how one view performs its rendering before the digest is generated.
Some code (finally)
lookup_context = ApplicationController.new.lookup_context
CacheDigests::TemplateDigestor.new("some_view.pdf", :html, lookup_context).digest # no problem here
CacheDigests::TemplateDigestor.new("some_view", :pdf, lookup_context).digest # boom!
To be clear. Both versions of the Digestor above work when run before the instantiated view renders. They both produce the same digest of the pdf formatted view. After render, though, the more correct one blows up. The template object is returned empty which causes a call to scan() to be done on nil.
This is somewhat similar to the failures I see trying to make the same patch to Rails master and takes me deep inside rails where I very easily get lost. I spent several hours in Rails master but haven't yet figured anything out.