Class: MethodObject::ObjectFactory

Inherits:
Object
  • Object
show all
Defined in:
lib/method_object.rb

Overview

Creates instances for delegation and caching method definitions.

Constant Summary collapse

STRUCT_DEFINITION =
lambda do |_class|
  def method_missing(name, *args)
    candidates = candidates_for_method_missing(name)
    handle_ambiguous_missing_method(candidates, name) if candidates.length > 1
    super
  end

  def respond_to_missing?(name, _include_private)
    candidates = candidates_for_method_missing(name)
    case candidates.length
    when 0
      return(super)
    when 1
      define_delegated_method(candidates.first)
    end
    true
  end

  def candidates_for_method_missing(method_name)
    potential_candidates =
      members.map do |attribute|
        PotentialDelegator.new(
          attribute,
          public_send(attribute),
          method_name,
        )
      end +
      members.map do |attribute|
        PotentialDelegatorWithPrefix.new(
          attribute,
          public_send(attribute),
          method_name,
        )
      end
    potential_candidates.select(&:candidate?)
  end

  def define_delegated_method(delegate)
    code = <<~RUBY
      def #{delegate.delegated_method}(*args, &block)
        #{delegate.attribute}
          .#{delegate.method_to_call_on_delegate}(*args, &block)
      end
    RUBY
    self.class.class_eval(code, __FILE__, __LINE__ + 1)
  end

  def handle_ambiguous_missing_method(candidates, method_name)
    raise(
      AmbigousMethodError,
      "#{method_name} is ambiguous: " +
      candidates
        .map do |candidate|
          "#{candidate.attribute}.#{candidate.method_to_call_on_delegate}"
        end
        .join(', '),
    )
  end
end

Class Method Summary collapse

Class Method Details

.create(*attributes) ⇒ Object



90
91
92
# File 'lib/method_object.rb', line 90

def self.create(*attributes)
  Struct.new(*attributes, keyword_init: true, &STRUCT_DEFINITION)
end