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 = "      def \#{delegate.delegated_method}(*args, &block)\n        \#{delegate.attribute}\n          .\#{delegate.method_to_call_on_delegate}(*args, &block)\n      end\n    RUBY\n    self.class.class_eval(code, __FILE__, __LINE__ + 1)\n  end\n\n  def handle_ambiguous_missing_method(candidates, method_name)\n    raise(\n      AmbigousMethodError,\n      \"\#{method_name} is ambiguous: \" +\n      candidates\n        .map do |candidate|\n          \"\#{candidate.attribute}.\#{candidate.method_to_call_on_delegate}\"\n        end\n        .join(', '),\n    )\n  end\nend\n"

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