56

So in Rails 3.2, ActiveSupport::Memoizable has been deprecated.

The message reads:

DEPRECATION WARNING: ActiveSupport::Memoizable is deprecated and
will be removed in future releases,simply use Ruby memoization
pattern instead.

It refers to "Ruby memoization pattern" (singular) as if there's one pattern we should all know and refer to...

I presume they mean something like:

def my_method
  @my_method ||= # ... go get the value
end

or

def my_method
  return @my_method if defined?(@my_method)

  @my_method = # ... go get the value
end

Is there something else I've missed?

jwfearn
  • 28,781
  • 28
  • 95
  • 122
bodacious
  • 6,608
  • 9
  • 45
  • 74
  • 1
    If you want 'false' or 'nil', it would not be saved using Ruby's memoizable. So if you want to implement your own memoizable wrapper, add a way to save 'false' and 'nil'. – JB Juliano May 05 '13 at 19:36
  • As a side note (stumbling over this ancient question), I've proposed "rose memoization" as the name for this pattern: https://thepugautomatic.com/2016/01/rose-memoization/ – Henrik N Apr 02 '21 at 10:17
  • 1
    @HenrikN I’ve stumbled upon your blog a few times. Nice to bump into you here – bodacious Apr 02 '21 at 10:18

4 Answers4

39

Here is the commit (and subsequent discussion) where Memoizable was deprecated: https://github.com/rails/rails/commit/36253916b0b788d6ded56669d37c96ed05c92c5c

The author advocates the @foo ||= ... approach and points to this commit as an example for migration: https://github.com/rails/rails/commit/f2c0fb32c0dce7f8da0ce446e2d2f0cba5fd44b3.

Edit: Note that I don't necessarily interpret this change as meaning that all instances of memoize can or should be replaced w/ this pattern. I read it as meaning that Memoizable is no longer needed/wanted in the Rails code itself. As the comments point out, Memoizable is much more than just a wrapper around @foo ||= .... If you need those features, go ahead and use Memoizable, you'll just have to get it from somewhere other than ActiveSupport (I'm guessing someone will fork a gem version, if they haven't already).

avaynshtok
  • 2,519
  • 1
  • 16
  • 14
33

Another option is to use the Memoist gem:

It is a direct extraction from ActiveSupport::Memoizable and can be used as a drop-in replacement. Just require 'memoist' and change

extend ActiveSupport::Memoizable

to

extend Memoist
Rory O'Kane
  • 29,210
  • 11
  • 96
  • 131
jcfischer
  • 524
  • 4
  • 5
2

Just an addition to the top answer, to memoize a class method use the following pattern:

class Foo
  class << self
    def bar
      @bar ||= begin
        # ...
      end
    end
  end
end
dsager
  • 388
  • 3
  • 9
0

Based upon the comments on the commit referenced above by avaynshtok, I’m going with this:

ActiveSupport::Deprecation.silence { extend ActiveSupport::Memoizable }

… because I figure I’ll know when Memoizable is ripped out of ActiveSupport from my RSpec suite dying right out of the starting gate.

Community
  • 1
  • 1
aec
  • 833
  • 1
  • 9
  • 18