Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Correct attribute memoization for ruby, made easy

branch: master

AttrMemoizer Build Status Bitdeli Badge

The common ruby idiom for attribute memoization looks like this:

class Example
  def field
    @field ||= some_expensive_task()

If some_expensive_task can return a "falsy" value (like nil or false), this doesn't work correctly—the prior memoized value of some_expensive_task will be ignored, and every subsequent call to field will result in another call to some_expensive_task.

AttrMemoizer aims to usurp your misbegotten love of ||=.


  1. include AttrMemoizer
  2. Call attr_memoizer with the attributes you want memoized
  3. Throw your @something ||= on the ground.
class Example
  include AttrMemoizer
  attr_memoizer :field, :another_field

  def field
    # code that computes field

  def another_field
    # code that computes another_field

Calling will call your definition of field, memoize the result for subsequent calls to an ivar called @field, and return that value.

Note that caching method results does not span instances:

class TimeHolder
  include AttrMemoizer
  attr_memoizer :a_time

  def a_time

t =
#> 2013-01-01 00:00:00 -0800
sleep 1
#> 2013-01-01 00:00:00 -0800 # < this is the memoized value

# But with a new instance, we get a new value:
#> 2013-01-01 20:26:41 -0800


To keep the metaprogramming demons at bay, we're using alias_method to rename the method—if you rename the attribute or look for consumers of the attribute, you at least has a chance of finding the attribute and their consumers, as opposed to how deferred_attribute worked, which made you call a method that only existed after the attr_memoizer method ran.

The problem with using alias_method at the time that attr_memoizer is called, is that the method may not be defined in the class yet. To get around this issue, we implement the class-level method_added hook, and set up the memoization after the method is defined.

If you are also using method_added, remember to call super at the end of your implementation. See the test cases for examples, and proof that this nonsense all works.


Add this line to your application's Gemfile:

gem 'attr_memoizer'

And then execute:

$ bundle



  • There were previous names for this library. We won't speak of them again.
Something went wrong with that request. Please try again.