method

memoize

memoize(*symbols)
public

No documentation available.

# File activesupport/lib/active_support/memoizable.rb, line 44
    def memoize(*symbols)
      symbols.each do |symbol|
        original_method = "_unmemoized_#{symbol}""_unmemoized_#{symbol}"
        memoized_ivar = MEMOIZED_IVAR.call(symbol)

        class_eval "include Freezable\n\nraise \"Already memoized \#{symbol}\" if method_defined?(:\#{original_method})\nalias \#{original_method} \#{symbol}\n\nif instance_method(:\#{symbol}).arity == 0\ndef \#{symbol}(reload = false)\nif reload || !defined?(\#{memoized_ivar}) || \#{memoized_ivar}.empty?\n\#{memoized_ivar} = [\#{original_method}.freeze]\nend\n\#{memoized_ivar}[0]\nend\nelse\ndef \#{symbol}(*args)\n\#{memoized_ivar} ||= {} unless frozen?\nreload = args.pop if args.last == true || args.last == :reload\n\nif defined?(\#{memoized_ivar}) && \#{memoized_ivar}\nif !reload && \#{memoized_ivar}.has_key?(args)\n\#{memoized_ivar}[args]\nelsif \#{memoized_ivar}\n\#{memoized_ivar}[args] = \#{original_method}(*args).freeze\nend\nelse\n\#{original_method}(*args)\nend\nend\nend\n", __FILE__, __LINE__
      end
    end

6Notes

Differences between normal or-assign operator

Mange · Mar 4, 200910 thanks

Differences between this method and normal memoization with ||=:

  • memoize works with false/nil values
  • Potential arguments are memoized

Take the following example: def allowed? @allowed ||= begin # Big calculation puts "Worked" false end end

allowed? # Outputs "Worked"
allowed? # Outputs "Worked" again

Since @allowed is set to false (this is also applicable with +nil+), the ||= operator will move on the the next statement and will not be short-circuited.

When you use memoize you will not have this problem. def allowed? # Big calculation puts "Worked" false end memoize :allowed?

allowed? # Outputs "Worked"
allowed? # No output

Now, look at the case where we have parameters: def random(max=10) @random ||= rand(max) end

random     # => 4
random     # => 4 -- Yay!
random(20) # => 4 -- Oops!

Better use memoize again! def random(max=10) rand(max) end memoize :random

random     # => 6
random     # => 6 -- Yay!
random(20) # => 12 -- Double-Yay!
random     # => 6 -- Head a'splode

Reloading memoized values

ville · Jan 20, 20095 thanks

Memoize is used to cache the result of a method. It's roughly equivalent of having:

def memoized_method(*args)
@result[args] ||= (
  # do calculation here
)
end

However, the result is cached so that it's not calculated for every request.

To recalculate cached value use either obj.memoized_method(:reload) or obj.memoized_method(true)

Remember to mixin the ActiveSupport::Memoizable module

rob-twf · Jan 16, 20094 thanks

To use memoize in your model you need to extend the model class with the module, like this:

class Person < ActiveRecord::Base
# Mixin the module
extend ActiveSupport::Memoizable

def expensive_method
  # do something that is worth remembering
end
memoize :expensive_method
end

If you use memoizable in most of your models you could consider mixing the module into all ActiveRecord models by doing this in an initializer:

ActiveRecord::Base.extend(ActiveSupport::Memoizable) 

Further To: Memoize will not cache singleton methods

treetoad · Jun 1, 20092 thanks

er...it will:

==== Code example

class PersonType < ActiveRecord::Base
class << self
  # Add the mixin here:
  extend ActiveSupport::Memoizable
  def mister
    find_by_name('Mister')
  end
  memoize :mister
end
end

Current version

szeryf · Oct 15, 20092 thanks

See ActiveSupport::Memoizable for un-deprecated version.

Memoize will not cache singleton methods

dvdplm · Mar 9, 2009

The following does not work: class PersonType < ActiveRecord::Base extend ActiveSupport::Memoizable class << self def mister find_by_name('Mister') end memoize :mister end

I guess one could extend the superclass, Class, with Memoizable support, but that seems Evil.