Skip to content

Instantly share code, notes, and snippets.

@btaitelb
Created November 22, 2016 05:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save btaitelb/9c362cbf0f06c4b0f66956cf69c3fd7c to your computer and use it in GitHub Desktop.
Save btaitelb/9c362cbf0f06c4b0f66956cf69c3fd7c to your computer and use it in GitHub Desktop.
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