lib/ruby_ext/declarative_cache.rb in ruby-ext-0.2.13 vs lib/ruby_ext/declarative_cache.rb in ruby-ext-0.2.15

- old
+ new

@@ -1,8 +1,8 @@ require 'monitor' -class Class +class Module def cache! *methods DeclarativeCache.cache! self, *methods end def cache_with_params! *methods @@ -11,162 +11,65 @@ end module DeclarativeCache DISABLED = false - warn "CASHE DISABLED" if DISABLED - - @versions, @alias_counter, @monitor = Hash.new{should! :be_never_called}, 0, Monitor.new - class << self + 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 alias_counter - @alias_counter += 1 - return :"m#{@alias_counter}" - end - - def cache! *arg - vnames, klass, methods = parse_and_check_arguments *arg - - return if DISABLED - methods.each do |m| - als = (m.to_s =~ /^[_a-zA-Z0-9]+$/) ? m : DeclarativeCache.alias_counter.to_sym - - klass.class_eval{alias_method :"cached_#{als}", :"#{m}"} - unless vnames.is_a? Array - script = single_version_without_args.interpolate binding - @versions[vnames] = 0 unless @versions.include? vnames - else - vnames_str = vnames.collect{|vname| "'#{vname}' => nil"}.join(', ') - script = multiple_version_without_args.interpolate binding - vnames.each{|vname| @versions[vname] = 0 unless @versions.include? vname} - end - klass.class_eval script, __FILE__, __LINE__ - end - end - - def cache_with_params! *arg - vnames, klass, methods = parse_and_check_arguments *arg - - return if DISABLED - methods.each do |m| - als = (m.to_s =~ /^[_a-zA-Z0-9]+$/) ? m : DeclarativeCache.alias_counter - - klass.class_eval{alias_method :"cached_#{als}", :"#{m}"} - unless vnames.is_a? Array - script = single_version_with_args.interpolate binding - @versions[vnames] = 0 unless @versions.include? vnames - else - vnames_str = vnames.collect{|vname| "'#{vname}' => nil"}.join(', ') - script = multiple_version_with_args.interpolate binding - vnames.each{|vname| @versions[vname] = 0 unless @versions.include? vname} - end - klass.class_eval script, __FILE__, __LINE__ - end - end - - def version name - @versions[name] - end - - def update *names - names.each do |n| - n = n.to_s - @versions[n] = 0 unless @versions.include? n - @versions[n] += 1 - end - end - - attr_reader :monitor - - protected - def parse_and_check_arguments *arg - arg.size.should! :>=, 2 - - if arg.size == 3 - version_names = arg.shift - if version_names.is_a? Array - version_names.size.should! :>, 0 - version_names = version_names.collect{|n| n.to_s} - else - version_names = version_names.to_s + 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 - - klass = arg.shift - else - version_names = klass = arg.shift end - - klass.class.should! :be, [Class, Module] - - methods = Array(arg.first) - defined = klass.instance_methods - methods.each do |m| - raise "Invalid method_name '#{m}'!" unless defined.include? m.to_s - end - return version_names, klass, methods - end - - def multiple_version_with_args - <<-RUBY - def \#{m} *params - DeclarativeCache.monitor.synchronize do - @cache_versions_\#{als} ||= {\#{vnames_str}} - @cache_value_\#{als} ||= {} - if @cache_versions_\#{als}.all?{|vname, v| v == DeclarativeCache.version(vname)} and @cache_value_\#{als}.include?(params) - return @cache_value_\#{als}[params] - else - @cache_versions_\#{als}.keys.each{|vname| @cache_versions_\#{als}[vname] = DeclarativeCache.version(vname)} - return @cache_value_\#{als}[params] = cached_\#{als}(*params) - end - end - end - RUBY - end - - def multiple_version_without_args - <<-RUBY - def \#{m} - DeclarativeCache.monitor.synchronize do - @cache_versions_\#{als} ||= {\#{vnames_str}} - if @cache_versions_\#{als}.all?{|vname, v| v == DeclarativeCache.version(vname)} - return @cache_value_\#{als} - else - @cache_versions_\#{als}.keys.each{|vname| @cache_versions_\#{als}[vname] = DeclarativeCache.version(vname)} - return @cache_value_\#{als} = cached_\#{als} - end - end - end - RUBY - end - - def single_version_with_args - <<-RUBY - def \#{m} *params - DeclarativeCache.monitor.synchronize do - @cache_value_\#{als} ||= {} - if @cache_version_\#{als} == DeclarativeCache.version("\#{vnames}") and @cache_value_\#{als}.include?(params) - return @cache_value_\#{als}[params] - else - @cache_version_\#{als} = DeclarativeCache.version("\#{vnames}") - return @cache_value_\#{als}[params] = cached_\#{als}(*params) - end - end - end - RUBY - end - - def single_version_without_args - <<-RUBY - def \#{m} - DeclarativeCache.monitor.synchronize do - if @cache_version_\#{als} == DeclarativeCache.version("\#{vnames}") - return @cache_value_\#{als} - else - @cache_version_\#{als} = DeclarativeCache.version("\#{vnames}") - return @cache_value_\#{als} = cached_\#{als} - end - end - end - RUBY - 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 \ No newline at end of file