lib/memoist.rb in memoist-0.13.0 vs lib/memoist.rb in memoist-0.14.0
- old
+ new
@@ -1,11 +1,11 @@
require 'memoist/core_ext/singleton_class'
module Memoist
def self.memoized_ivar_for(method_name, identifier=nil)
- "@#{memoized_prefix(identifier)}_#{escape_punctuation(method_name.to_s)}"
+ "@#{memoized_prefix(identifier)}_#{escape_punctuation(method_name)}"
end
def self.unmemoized_method_for(method_name, identifier=nil)
"#{unmemoized_prefix(identifier)}_#{method_name}".to_sym
end
@@ -25,14 +25,14 @@
"_unmemoized".freeze
end
end
def self.escape_punctuation(string)
+ string = string.is_a?(String) ? string.dup : string.to_s
+
return string unless string.end_with?('?'.freeze, '!'.freeze)
- string = string.dup
-
# A String can't end in both ? and !
if string.sub!(/\?\Z/, '_query'.freeze)
else
string.sub!(/!\Z/, '_bang'.freeze)
end
@@ -61,41 +61,64 @@
def unmemoize_all
flush_cache
end
+ def memoized_structs(names)
+ structs = self.class.all_memoized_structs
+ return structs if names.empty?
+
+ structs.select { |s| names.include?(s.memoized_method) }
+ end
+
def prime_cache(*method_names)
- method_names = self.class.memoized_methods if method_names.empty?
- method_names.each do |method_name|
- if method(Memoist.unmemoized_method_for(method_name)).arity == 0
- __send__(method_name)
+ memoized_structs(method_names).each do |struct|
+ if struct.arity == 0
+ __send__(struct.memoized_method)
else
- ivar = Memoist.memoized_ivar_for(method_name)
- instance_variable_set(ivar, {})
+ instance_variable_set(struct.ivar, {})
end
end
end
def flush_cache(*method_names)
- method_names = self.class.memoized_methods if method_names.empty?
+ memoized_structs(method_names).each do |struct|
+ remove_instance_variable(struct.ivar) if instance_variable_defined?(struct.ivar)
+ end
+ end
+ end
- method_names.each do |method_name|
- ivar = Memoist.memoized_ivar_for(method_name)
- remove_instance_variable(ivar) if instance_variable_defined?(ivar)
+ MemoizedMethod = Struct.new(:memoized_method, :ivar, :arity)
+
+ def all_memoized_structs
+ @all_memoized_structs ||= begin
+ structs = memoized_methods.dup
+
+ # Collect the memoized_methods of ancestors in ancestor order
+ # unless we already have it since self or parents could be overriding
+ # an ancestor method.
+ ancestors.grep(Memoist).each do |ancestor|
+ ancestor.memoized_methods.each do |m|
+ structs << m unless structs.any? {|am| am.memoized_method == m.memoized_method }
+ end
end
+ structs
end
end
+ def clear_structs
+ @all_memoized_structs = nil
+ end
+
def memoize(*method_names)
if method_names.last.is_a?(Hash)
identifier = method_names.pop[:identifier]
end
Memoist.memoist_eval(self) do
def self.memoized_methods
- require 'set'
- @_memoized_methods ||= Set.new
+ @_memoized_methods ||= []
end
end
method_names.each do |method_name|
unmemoized_method = Memoist.unmemoized_method_for(method_name, identifier)
@@ -108,11 +131,12 @@
warn "Already memoized #{method_name}"
return
end
alias_method unmemoized_method, method_name
- self.memoized_methods << method_name
- if instance_method(method_name).arity == 0
+ mm = MemoizedMethod.new(method_name, memoized_ivar, instance_method(method_name).arity)
+ self.memoized_methods << mm
+ if mm.arity == 0
# define a method like this;
# def mime_type(reload=true)
# skip_cache = reload || !instance_variable_defined?("@_memoized_mime_type")