memoize
- 1.0.0
- 1.1.6
- 1.2.6
- 2.0.3
- 2.1.0
- 2.2.1 (0)
- 2.3.8
- 3.0.0
- 3.0.9
- 3.1.0
- 3.2.1
- 3.2.8
- 3.2.13
- 4.0.2
- 4.1.8
- 4.2.1
- 4.2.7
- 4.2.9
- 5.0.0.1
- 5.1.7
- 5.2.3
- 6.0.0
- 6.1.3.1
- 6.1.7.7
- 7.0.0
- 7.1.3.2
- 7.1.3.4
- What's this?
Differences between normal or-assign operator
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
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
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
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
See ActiveSupport::Memoizable for un-deprecated version.
Memoize will not cache singleton methods
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.