class Memoizable::MethodBuilder

Build the memoized method

Attributes

original_method[R]

The original method before memoization

@return [UnboundMethod]

@api public

Public Class Methods

new(descendant, method_name, freezer) click to toggle source

Initialize an object to build a memoized method

@param [Module] descendant @param [Symbol] method_name @param [#call] freezer

@return [undefined]

@api private

# File lib/memoizable/method_builder.rb, line 55
def initialize(descendant, method_name, freezer)
  @descendant          = descendant
  @method_name         = method_name
  @freezer             = freezer
  @original_visibility = visibility
  @original_method     = @descendant.instance_method(@method_name)
  assert_arity(@original_method.arity)
end

Public Instance Methods

call() click to toggle source

Build a new memoized method

@example

method_builder.call  # => creates new method

@return [MethodBuilder]

@api public

# File lib/memoizable/method_builder.rb, line 72
def call
  remove_original_method
  create_memoized_method
  set_method_visibility
  self
end

Private Instance Methods

assert_arity(arity) click to toggle source

Assert the method arity is zero

@param [Integer] arity

@return [undefined]

@raise [InvalidArityError]

@api private

# File lib/memoizable/method_builder.rb, line 90
def assert_arity(arity)
  if arity.nonzero?
    fail InvalidArityError.new(@descendant, @method_name, arity)
  end
end
create_memoized_method() click to toggle source

Create a new memoized method

@return [undefined]

@api private

# File lib/memoizable/method_builder.rb, line 111
def create_memoized_method
  name, method, freezer = @method_name, @original_method, @freezer
  @descendant.module_eval do
    define_method(name) do |&block|
      fail BlockNotAllowedError.new(self.class, name) if block
      memoized_method_cache.fetch(name) do
        freezer.call(method.bind(self).call)
      end
    end
  end
end
remove_original_method() click to toggle source

Remove the original method

@return [undefined]

@api private

# File lib/memoizable/method_builder.rb, line 101
def remove_original_method
  name = @method_name
  @descendant.module_eval { undef_method(name) }
end
set_method_visibility() click to toggle source

Set the memoized method visibility to match the original method

@return [undefined]

@api private

# File lib/memoizable/method_builder.rb, line 128
def set_method_visibility
  @descendant.send(@original_visibility, @method_name)
end
visibility() click to toggle source

Get the visibility of the original method

@return [Symbol]

@api private

# File lib/memoizable/method_builder.rb, line 137
def visibility
  if    @descendant.private_method_defined?(@method_name)   then :private
  elsif @descendant.protected_method_defined?(@method_name) then :protected
  else                                                           :public
  end
end