I followed Niklas Hofer's general solution, but I found that his implementation did not match the exact semantics of the Rails cache helper. Namely, it attempted to return the cached HTML from the helper, rather than writing it to the buffer using safe_concat
, which is what the Rails helper does.
The Rails helper usage is like this:
- cache do
= something
Whereas his solution required this syntax:
= cache_with_updated_csrf do
= something
For consistency, I would prefer that these work the same way. Hence I used this syntax:
- cache_form do
= something
Here is my implementation. It will also skip caching when caching is disabled, like the Rails helper does.
module CacheHelper
# Cache a form with a fresh CSRF
def cache_form(name = {}, options = nil, &block)
if controller.perform_caching
fragment = fragment_for(name, options, &block)
fragment_with_fresh_csrf = Nokogiri::HTML::DocumentFragment.parse( fragment ).tap do |doc|
doc.css("input[name=#{request_forgery_protection_token}]").each { |e| e['value'] = form_authenticity_token }
end.to_html
safe_concat fragment_with_fresh_csrf
else
yield
end
nil
end
end