class Docile::FallbackContextProxy

rubocop:disable Style/MissingRespondToMissing
@see Docile.dsl_eval
This is useful for implementing DSL evaluation in the context of an object.
method.
and then to the fallback receiver if the primary does not handle that
Will attempt to forward all method calls first to the primary receiver,
fallback receiver.
A proxy object with a primary receiver as well as a secondary
@api private

def initialize(receiver, fallback)

Parameters:
  • fallback (Object) -- the fallback proxy target to which any methods
  • receiver (Object) -- the primary proxy target to which all methods
def initialize(receiver, fallback)
  @__receiver__ = receiver
  @__fallback__ = fallback
  # Enables calling DSL methods from helper methods in the block's context
  unless fallback.respond_to?(:method_missing)
    # NOTE: We could switch to {#define_singleton_method} on current Rubies
    singleton_class = (class << fallback; self; end)
    # instrument {#method_missing} on the block's context to fallback to
    # the DSL object. This allows helper methods in the block's context to
    # contain calls to methods on the DSL object.
    singleton_class.
      send(:define_method, :method_missing) do |method, *args, &block|
        m = method.to_sym
        if !NON_FALLBACK_METHODS.member?(m) &&
           !fallback.respond_to?(m) &&
           receiver.respond_to?(m)
          receiver.__send__(method.to_sym, *args, &block)
        else
          super(method, *args, &block)
        end
      end
    if singleton_class.respond_to?(:ruby2_keywords, true)
      singleton_class.send(:ruby2_keywords, :method_missing)
    end
    # instrument a helper method to remove the above instrumentation
    singleton_class.
      send(:define_method, :__docile_undo_fallback__) do
        singleton_class.send(:remove_method, :method_missing)
        singleton_class.send(:remove_method, :__docile_undo_fallback__)
      end
  end
end

def instance_variables

Returns:
  • (Array) - Instance variable names, excluding
def instance_variables
  super.reject { |v| NON_PROXIED_INSTANCE_VARIABLES.include?(v) }
end

def method_missing(method, *args, &block)

and then to `fallback` if not found.
Proxy all methods, excluding {NON_PROXIED_METHODS}, first to `receiver`
def method_missing(method, *args, &block)
  if @__receiver__.respond_to?(method.to_sym)
    @__receiver__.__send__(method.to_sym, *args, &block)
  else
    begin
      @__fallback__.__send__(method.to_sym, *args, &block)
    rescue NoMethodError => e
      e.extend(BacktraceFilter)
      raise e
    end
  end
end