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