module LaserLemon module CacheFlow def self.included(base) base.class_eval do class_inheritable_accessor :cache_serialization self.cache_serialization = false extend ClassMethods include InstanceMethods alias_method_chain :to_xml, :cache_flow alias_method_chain :to_json, :cache_flow end end module ClassMethods def cache_flow(value = true) if block_given? old_value = cache_serialization begin self.cache_serialization = value yield ensure self.cache_serialization = old_value end else self.cache_serialization = value end end end module InstanceMethods def to_xml_with_cache_flow(options = {}) with_cache_flow(:xml, options) do to_xml_without_cache_flow(options) end end def to_json_with_cache_flow(options = {}) with_cache_flow(:json, options) do to_json_without_cache_flow(options) end end private def with_cache_flow(extension, options, &block) if options.has_key?(:cache) ? options.delete(:cache) : self.class.cache_serialization options.merge!(:cache => false) key, value = send("#{extension}_cache_key", options), yield Rails.cache.fetch(key){ value.respond_to?(:dup) ? value.dup : value } else yield end end def xml_cache_key(options) level = options.has_key?(:builder) ? options[:builder].instance_eval{ @level } : nil serialized_cache_key(:xml, options.except(:builder).merge(:level => level)) end def json_cache_key(options) serialized_cache_key(:json, options) end def serialized_cache_key(extension, options) query = options.except(:cache).reject{|k,v| v.nil? }.to_query ["#{cache_key}.#{extension}", query].delete_if(&:blank?).join('?') end end end end ActiveRecord::Base.send(:include, LaserLemon::CacheFlow)