Memoization caches the result of an expensive computation so repeated calls return instantly. This lesson covers the @variable ||= pattern, the memoized gem, and when memoization is dangerous.
Important
Work on this lesson in
teachermode.
Learning goals
- You can explain what memoization is and when it pays off: expensive work that is repeated with the same input during an object's lifetime.
- You can memoize a method's result, e.g. with the
@value ||= …idiom, and explain why that idiom fails fornilandfalse. - You can memoize with a library like our
memoizedgem, and explain what it handles better than the idiom. - You can explain why memoizing an instance method is usually safe while memoizing a class method is dangerous in a long-running process.
- You can explain why
||is a poor way to set defaults.
Resources
Read what's new to you, skim what's familiar, skip what you already master. Stop when you can meet the learning goals.
Your agent can also generate an overview, a tutorial or an explanation for anything here, tailored to what you already know. Just ask.
- 📄 Speeding up Rails with Memoization Show archive.org snapshot
- 📄
4 Simple Memoization Patterns in Ruby (And One Gem)
Show archive.org snapshot
— including why
||=fails fornilandfalse - 📄 memoized Show archive.org snapshot — README of our gem
- 📄 Caution:
||to set defaults — our card on the related trap
Exercises
Write a class WebsiteSizer that measures the number of characters in the given URL's HTML body:
website_sizer = WebsiteSizer.new
website_sizer.size_of('https://makandra.com') # => 27448
website_sizer.size_of('https://railslts.com') # => 2145364
You can use any library to perform the actual HTTP request.
The class should cache its results so subsequent calls for the same URLs return the HTML size instantly, without making an additional HTTP request.
Write three versions of WebsiteSizer:
- A version that manually caches the results in some Ruby data structure
- A version that caches using the
memoizedgem. - A version that memoizes a class method
WebsiteSizer.size_of(url)instead. It works — now explain in one or two sentences why this is dangerous in a long-running server process, and when this cache would ever be emptied.