Created
November 22, 2016 05:12
-
-
Save btaitelb/9c362cbf0f06c4b0f66956cf69c3fd7c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Cacheable | |
def self.extended(base) | |
@@unaliased_methods = {} | |
@@cacheable_methods = Module.new | |
end | |
def method_added(m) | |
if @@unaliased_methods[m] | |
cache_method(m) | |
@@unaliased_methods[m] = false | |
if @@unaliased_methods.values.none? | |
prepend_cached_methods | |
end | |
end | |
end | |
## uncommenting the commented lines here allows a subclass to cache | |
## methods from a parent class, but this leads to unexpected results | |
## when trying to override the method. | |
## | |
## As it's written here, the `caches` line must come before the methods | |
## are defined | |
def caches(*method_names) | |
# prepend_now = true | |
method_names.each do |m| | |
# if instance_methods.include?(m) | |
# cache_method(m) | |
# else | |
@@unaliased_methods[m] = true | |
# prepend_now = false | |
# end | |
end | |
# prepend_cached_methods if prepend_now | |
end | |
private | |
def cache_method(name) | |
self.send(:alias_method, "#{name}_uncached", name) | |
@@cacheable_methods.send(:define_method, name) do |*args| | |
# puts "I am the cached version of #{name}" | |
@cached_result ||= self.send("#{name}_uncached", *args) | |
end | |
end | |
def prepend_cached_methods | |
self.prepend(@@cacheable_methods) | |
end | |
end | |
class Animal | |
extend Cacheable | |
caches :long_running_method | |
attr_accessor :name, :age | |
def initialize(name, age=42) | |
@name = name | |
@age = age | |
end | |
def greeting | |
"I am #{name} and I am #{long_running_method} years old." | |
end | |
def long_running_method | |
puts "in long running method..." | |
sleep 5 | |
@age | |
end | |
end | |
class Dog < Animal | |
extend Cacheable # not really needed, but for isolation | |
caches :greeting | |
def greeting | |
sleep 3 | |
"this is a different greeting" | |
end | |
end | |
animal = Animal.new("Human") | |
puts animal.greeting | |
puts animal.greeting | |
dog = Dog.new("Rufus", 6) | |
puts dog.greeting | |
puts dog.greeting |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment