Created
March 29, 2011 06:30
-
-
Save stackng/891895 to your computer and use it in GitHub Desktop.
make action and fragment caching of rails3 compatible with content_for
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActionController | |
class Metal | |
attr_internal :cached_content_for | |
end | |
module Caching | |
module Actions | |
def _save_fragment(name, options) | |
return unless caching_allowed? | |
content = response_body | |
content = content.join if content.is_a?(Array) | |
content = cached_content_for.merge(:layout => content) if cached_content_for.is_a?(Hash) | |
write_fragment(name, content, options) | |
end | |
end | |
module Fragments | |
def write_fragment_with_content_to_cache(key, content, options = nil) | |
return_content = write_fragment_without_content_to_cache(key, content, options) | |
return_content.is_a?(Hash) ? return_content[:layout] : return_content | |
end | |
def read_fragment_with_content_to_cache(key, options = nil) | |
result = read_fragment_without_content_to_cache(key, options) | |
if (result.is_a?(Hash)) | |
result = result.dup if result.frozen? | |
fragment = result.delete(:layout) | |
self.cached_content_for = (self.cached_content_for || {}).merge(result) | |
result = fragment | |
end | |
result.respond_to?(:html_safe) ? result.html_safe : result | |
end | |
alias_method_chain :write_fragment, :content_to_cache | |
alias_method_chain :read_fragment, :content_to_cache | |
end | |
end | |
end | |
module ActionView | |
module Rendering | |
# Added to support implementation of action caching | |
def _render_template_with_cached_content_for(template, layout = nil, options = {}) | |
if controller.respond_to?('caching_allowed?') && controller.caching_allowed? | |
controller.cached_content_for.each { |k, v| content_for(k, v) unless content_for?(k) } if controller.cached_content_for.is_a?(Hash) | |
return_value = _render_template_without_cached_content_for(template, layout, options) | |
controller.cached_content_for = content_to_cache | |
elsif | |
return_value = _render_template_without_cached_content_for(template, layout, options) | |
end | |
return_value | |
end | |
alias_method_chain :_render_template, :cached_content_for | |
end | |
module Helpers | |
module CaptureHelper | |
# Added to support implementation of fragment caching | |
def cache_with_content_for #:nodoc:# | |
@_subset_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new } | |
yield | |
ensure | |
@_subset_content_for = nil | |
end | |
# Added to support implementation of action caching | |
def content_to_cache #:nodoc:# | |
cache_this = @_subset_content_for || @_content_for.except(:layout) | |
cache_this.dup.tap {|h| h.default = nil } | |
end | |
# Overwrite content_for to support fragment caching | |
def content_for(name, content = nil, &block) | |
content = capture(&block) if block_given? | |
@_content_for[name] << content if content | |
@_subset_content_for[name] << content if content && @_subset_content_for | |
@_content_for[name] unless content | |
end | |
end | |
module CacheHelper | |
def fragment_for(name = {}, options = nil, &block) #:nodoc: | |
if controller.fragment_exist?(name, options) | |
fragment = controller.read_fragment(name, options) | |
controller.cached_content_for.each { |k, v| content_for(k, v) unless content_for?(k) } if controller.cached_content_for.is_a?(Hash) | |
fragment | |
else | |
pos = output_buffer.length | |
hash_to_cache = nil | |
cache_with_content_for do | |
yield | |
fragment = output_buffer.slice!(pos..-1) | |
hash_to_cache = {:layout => fragment}.merge(content_to_cache) | |
end | |
controller.write_fragment(name, hash_to_cache, options) | |
end | |
end | |
end | |
end | |
end |
Has anyone updated this to work with Rails 3.1?
This is what I did to get content_for working with action caching in Rails 3.1 (and I think Rails 3.2, but haven't tested yet): https://gist.github.com/2485272
Has anyone updated this to work with recent Rails (5.2 or 6)?
All right, I finally got this working on Rails 5.2 (which is the version I'm still on).
Here is my fork/patch , and a demo app that uses it.
Now to submit a merge request to rails (see feature proposal) ...
I've submitted a pull request here, in case you're interested: rails/rails#39600
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My version of this gist =)
https://gist.github.com/1315929
Supports nested 'cache do' blocks
and some fixes