ContextualMemery
ContextualMemery builds on the memery gem to
let you turn memoization on and off at runtime, scoped to a block, for one or more methods,
on either an instance or a class.
Where memery memoizes a method for the lifetime of the object, ContextualMemery memoizes a
method only for the duration of a block:
instance.banana_time # not memoized
instance.banana_time # not memoized, recomputed
instance.memoized(:banana_time) do
instance.banana_time # computed
instance.banana_time # cached
end
instance.banana_time # not memoized again, cache has been cleared
This is handy when you want to memoize a call for the duration of a request, a job, a loop iteration, etc., without permanently memoizing it for the object's whole lifetime.
Installation
Install the gem and add to the application's Gemfile by executing:
bundle add contextual_memery
Usage
Include ContextualMemery in your class:
class Thing
include ContextualMemery
def banana_time(*)
...
end
def handyman
...
end
def self.take_back(*)
...
end
end
This gives both instances and the class a memoized method.
On an instance
instance = Thing.new
instance.memoized(:banana_time) do
instance.banana_time
instance.banana_time # cached
instance.handyman # not memoized, still recomputed every call
end
Pass several method names to memoize more than one method at once:
instance.memoized(:banana_time, :douglas) do
...
end
Pass :all, or no arguments at all, to memoize every method defined directly on the object
(public, protected and private) for the duration of the block:
instance.memoized(:all) do
...
end
instance.memoized do
...
end
On a class
The exact same API is available on the class itself, for memoizing class (singleton) methods:
Thing.memoized(:take_back) do
Thing.take_back
Thing.take_back # cached
end
Scoped to the block, including indirect calls
Memoization is active for any call made from within the block, even indirectly through other
methods — it isn't limited to calls written literally inside the do...end:
def do_thing(onion)
Thing.take_back(onion)
end
Thing.memoized(:take_back) do
foods.each do |food|
do_thing(food.skin) # each unique `food.skin` is only computed once
end
end
Scoping and nesting
- Memoization is scoped per object: memoizing
instance_anever affectsinstance_b, and memoizing an instance never affects the class (or vice versa). - Arguments are still taken into account, exactly like plain
memery:banana_time(1)andbanana_time(2)are cached separately. - The cache is cleared as soon as the outermost
memoizedblock for that object finishes, so nestingmemoizedblocks on the same object is safe and won't clear the cache out from under an enclosing block.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to
run the tests. You can also run bin/console for an interactive prompt that will allow you to
experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new
version, update the version number in version.rb, and then run bundle exec rake release,
which will create a git tag for the version, push git commits and the created tag, and push the
.gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/braindeaf/contextual_memery.
License
The gem is available as open source under the terms of the MIT License.