mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Allow memoized methods to be reloaded and allow multiple symbols
This commit is contained in:
parent
7430c4168f
commit
e1f23da53c
2 changed files with 44 additions and 29 deletions
|
@ -5,28 +5,30 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
module ClassMethods
|
||||
def memoize(symbol)
|
||||
original_method = "_unmemoized_#{symbol}"
|
||||
memoized_ivar = "@_memoized_#{symbol}"
|
||||
raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
|
||||
def memoize(*symbols)
|
||||
symbols.each do |symbol|
|
||||
original_method = "unmemoized_#{symbol}"
|
||||
memoized_ivar = "@#{symbol}"
|
||||
raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
|
||||
|
||||
alias_method original_method, symbol
|
||||
class_eval <<-EOS, __FILE__, __LINE__
|
||||
def #{symbol}
|
||||
if defined? #{memoized_ivar}
|
||||
#{memoized_ivar}
|
||||
else
|
||||
#{memoized_ivar} = #{original_method}
|
||||
alias_method original_method, symbol
|
||||
class_eval <<-EOS, __FILE__, __LINE__
|
||||
def #{symbol}(reload = false)
|
||||
if !reload && defined? #{memoized_ivar}
|
||||
#{memoized_ivar}
|
||||
else
|
||||
#{memoized_ivar} = #{original_method}.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
EOS
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def freeze
|
||||
methods.each do |method|
|
||||
if m = method.to_s.match(/\A_unmemoized_(.*)/)
|
||||
send(m[1]).freeze
|
||||
if m = method.to_s.match(/\Aunmemoized_(.*)/)
|
||||
send(m[1])
|
||||
end
|
||||
end
|
||||
super
|
||||
|
|
|
@ -8,12 +8,16 @@ uses_mocha 'Memoizable' do
|
|||
def name
|
||||
fetch_name_from_floppy
|
||||
end
|
||||
memoize :name
|
||||
|
||||
def age
|
||||
nil
|
||||
end
|
||||
memoize :age
|
||||
|
||||
def random
|
||||
rand(0)
|
||||
end
|
||||
|
||||
memoize :name, :age, :random
|
||||
|
||||
private
|
||||
def fetch_name_from_floppy
|
||||
|
@ -21,25 +25,34 @@ uses_mocha 'Memoizable' do
|
|||
end
|
||||
end
|
||||
|
||||
def test_memoization
|
||||
person = Person.new
|
||||
assert_equal "Josh", person.name
|
||||
def setup
|
||||
@person = Person.new
|
||||
end
|
||||
|
||||
person.expects(:fetch_name_from_floppy).never
|
||||
2.times { assert_equal "Josh", person.name }
|
||||
def test_memoization
|
||||
assert_equal "Josh", @person.name
|
||||
|
||||
@person.expects(:fetch_name_from_floppy).never
|
||||
2.times { assert_equal "Josh", @person.name }
|
||||
end
|
||||
|
||||
def test_reloadable
|
||||
random = @person.random
|
||||
assert_equal random, @person.random
|
||||
assert_not_equal random, @person.random(:reload)
|
||||
end
|
||||
|
||||
def test_memoized_methods_are_frozen
|
||||
person = Person.new
|
||||
person.freeze
|
||||
assert_equal "Josh", person.name
|
||||
assert_equal true, person.name.frozen?
|
||||
assert_equal true, @person.name.frozen?
|
||||
|
||||
@person.freeze
|
||||
assert_equal "Josh", @person.name
|
||||
assert_equal true, @person.name.frozen?
|
||||
end
|
||||
|
||||
def test_memoization_frozen_with_nil_value
|
||||
person = Person.new
|
||||
person.freeze
|
||||
assert_equal nil, person.age
|
||||
@person.freeze
|
||||
assert_equal nil, @person.age
|
||||
end
|
||||
|
||||
def test_double_memoization
|
||||
|
|
Loading…
Reference in a new issue