Ruby - Memoization proxy class
I've needed to create a proxy class that would cache the method results from an object because I couldn't change its implementation.
It had a lot of expensive operations that would be done for every method call, and some of these heavy methods would be called internally, and that's why I needed to come with an "intrusive" solution.
It's important to note that you probably want to avoid using something like this, you probably will always prefer to design your code better over to using this hack. Also, it's needless to say that this will give you problems in case your methods are not referentially transparent or produce side effects.
class MethodCacheProxy
  instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
  attr_reader :target, :cache, :invasive
  def initialize(target, invasive = false)
    @target = target
    @cache = {}
    @invasive = invasive
    intercept_instance_methods if invasive
  end
  def method_missing(name, *args, &block)
    cache_for(name, *args, &block)
  end
  def cache_for(name, *args, &block)
    unless block_given?
      cache[cache_key_for(name, args)] ||= target.send(name, *args)
    else
      target.send(name, *args, &block)
    end
  end
  def cache_key_for(name, args)
    "#{name}_#{args.hash}"
  end
  private
  def intercept_instance_methods
    instance_methods.each do |name|
      override_method(name)
    end
  end
  def instance_methods
    target.class.instance_methods(false)
  end
  def instance_method(name)
    target.class.instance_method(name)
  end
  def override_method(name)
    cacher = self
    method = instance_method(name)
    target.define_singleton_method(name) do |*args, &block|
      unless block.present?
        cache_key = cacher.cache_key_for(name, args)
        cacher.cache[cache_key] ||= method.bind(self).(*args, &block)
      else
        method.bind(self).(*args, &block)
      end
    end
  end
endWritten by David Michael Nelson
Related protips
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
 #Ruby 
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#

 
 
 
 
