diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index d06250171a2b3..c41feef4c739a 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -5,28 +5,30 @@ def self.included(base) #:nodoc: 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 diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb index fc24a2942d7e7..b649b31455552 100644 --- a/activesupport/test/memoizable_test.rb +++ b/activesupport/test/memoizable_test.rb @@ -8,12 +8,16 @@ class Person 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 @@ def fetch_name_from_floppy end end + def setup + @person = Person.new + end + def test_memoization - person = Person.new - assert_equal "Josh", person.name + assert_equal "Josh", @person.name + + @person.expects(:fetch_name_from_floppy).never + 2.times { assert_equal "Josh", @person.name } + end - person.expects(:fetch_name_from_floppy).never - 2.times { assert_equal "Josh", person.name } + 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