cubesystems/releaf

View on GitHub
releaf-core/lib/releaf/instance_cache.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Releaf::InstanceCache
  extend ActiveSupport::Concern

  included do
    cattr_accessor :cached_instance_methods, :instance_methods_to_cache

    self.cached_instance_methods   = []
    self.instance_methods_to_cache = []

    def self.instance_cache_original_method_name(method_name)
      "instance_cache_original_#{method_name}"
    end

    if respond_to?(:method_added)
      # preserve any previous definitions of method_added
      singleton_class.send(:alias_method, instance_cache_original_method_name(:method_added), :method_added)
    end

    def self.method_added(method_name)
      # call previous definition of method_added if present
      parent_method_added = instance_cache_original_method_name(:method_added)
      send(parent_method_added, method_name) if respond_to?(parent_method_added)

      # see if the newly added method is in the queue needing to be cached
      method_needs_to_be_cached = instance_methods_to_cache.delete(method_name)
      if method_needs_to_be_cached.present?
        create_instance_cache_method_alias(method_name)
      end
    end

    def self.cache_instance_methods(*method_names)
      method_names.each { |method_name| cache_instance_method(method_name) }
    end

    def self.cache_instance_method method_name
      if instance_methods.include?(method_name)
        # method already defined, alias it
        create_instance_cache_method_alias method_name
      else
        # method not defined yet, add to queue
        instance_methods_to_cache << method_name
      end
    end

    def self.create_instance_cache_method_alias method_name
      original_method_name = instance_cache_original_method_name( method_name )
      alias_method original_method_name, method_name
      define_method(method_name) do
        instance_cache(method_name) do
          send(original_method_name)
        end
      end
      self.cached_instance_methods << method_name
    end
  end

  def instance_cache_store
    @instance_cache_store ||= {}
  end

  def reset_instance_cache
    @instance_cache_store = {}
  end

  def instance_cache(key)
    if instance_cache_store.key?(key)
      instance_cache_store[key]
    else
      instance_cache_store[key] = yield
    end
  end
end