require 'monitor' class Module def cache! *methods DeclarativeCache.cache! self, *methods end def cache_with_params! *methods DeclarativeCache.cache_with_params! self, *methods end end module DeclarativeCache DISABLED = false warn "CASHE DISABLED" if DISABLED unless DISABLED class << self def alias_counter @alias_counter ||= 0 @alias_counter += 1 return "cached_method_#{@alias_counter}" end def cache! klass, *methods methods.each do |method| klass.class_eval do als = (method.to_s =~ /^[_a-zA-Z0-9]+$/) ? "cached_#{method}" : DeclarativeCache.alias_counter.to_sym iv_check = "@#{als}_check" iv = "@#{als}" alias_method als, method define_method method do |*args| args.should! :be_empty unless cached = instance_variable_get(iv) unless check = instance_variable_get(iv_check) cached = send als instance_variable_set iv, cached instance_variable_set iv_check, true end end cached end end end end def cache_with_params! klass, *methods methods.each do |method| klass.class_eval do als = (method.to_s =~ /^[_a-zA-Z0-9]+$/) ? "cached_#{method}" : DeclarativeCache.alias_counter.to_sym iv = "@#{als}" alias_method als, method define_method method do |*args| unless results = instance_variable_get(iv) results = {} instance_variable_set iv, results end unless results.include? args results[args] = send als, *args end results[args] end end end end end end end