class Grape::API

should subclass this class in order to build an API.
The API class is the primary entry point for creating Grape APIs. Users

def add_setup(method, *args, &block)

Adds a new stage to the set up require to get a Grape::API up and running
def add_setup(method, *args, &block)
  setup_step = { method: method, args: args, block: block }
  @setup += [setup_step]
  last_response = nil
  @instances.each do |instance|
    last_response = replay_step_on(instance, setup_step)
  end
  # Updating all previously mounted classes in the case that new methods have been executed.
  if method != :mount && @setup.any?
    previous_mount_steps = @setup.select { |step| step[:method] == :mount }
    previous_mount_steps.each do |mount_step|
      refresh_mount_step = mount_step.merge(method: :refresh_mounted_api)
      @setup += [refresh_mount_step]
      @instances.each do |instance|
        replay_step_on(instance, refresh_mount_step)
      end
    end
  end
  last_response
end

def any_lazy?(args)

def any_lazy?(args)
  args.any? { |argument| argument.respond_to?(:lazy?) && argument.lazy? }
end

def call(...)

NOTE: This will only be called on an API directly mounted on RACK
(http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
the headers, and the body. See [the rack specification]
from Rack and ultimately returns an array of three values: the status,
This is the interface point between Rack and Grape; it accepts a request
def call(...)
  instance_for_rack.call(...)
end

def compile!

def compile!
  instance_for_rack.compile! # See API::Instance.compile!
end

def configure

`configuration` as normal.
The configuration set here is accessible from inside an API with
API. If no block is given, returns the configuration hash.
configuration hash to the block which you can use to configure your
Configure an API from the outside. If a block is given, it'll pass a
def configure
  config = @base_instance.configuration
  if block_given?
    yield config
    self
  else
    config
  end
end

def evaluate_arguments(configuration, *args)

def evaluate_arguments(configuration, *args)
  args.map do |argument|
    if argument.respond_to?(:lazy?) && argument.lazy?
      argument.evaluate_from(configuration)
    elsif argument.is_a?(Hash)
      argument.transform_values { |value| evaluate_arguments(configuration, value).first }
    elsif argument.is_a?(Array)
      evaluate_arguments(configuration, *argument)
    else
      argument
    end
  end
end

def inherited(api)

It will listen to the setup required to mount that endpoint, and replicate it on any new instance
When inherited, will create a list of all instances (times the API was mounted)
def inherited(api)
  super
  api.initial_setup(self == Grape::API ? Grape::API::Instance : @base_instance)
  api.override_all_methods!
end

def initial_setup(base_instance_parent)

an instance that will be used to create the set up but will not be mounted
Initialize the instance variables on the remountable class, and the base_instance
def initial_setup(base_instance_parent)
  @instances = []
  @setup = []
  @base_parent = base_instance_parent
  @base_instance = mount_instance
end

def instance_for_rack

def instance_for_rack
  if never_mounted?
    base_instance
  else
    mounted_instances.first
  end
end

def method_missing(method, *args, &block)

def method_missing(method, *args, &block)
  # If there's a missing method, it may be defined on the base_instance instead.
  if respond_to_missing?(method)
    base_instance.send(method, *args, &block)
  else
    super
  end
end

def mount_instance(opts = {})

too much, you may actually want to provide a new API rather than remount it.
depending on where the endpoint is mounted. Use with care, if you find yourself using configuration
For instance, a description could be done using: `desc configuration[:description]` if it may vary
The remountable class can have a configuration hash to provide some dynamic class-level variables.
def mount_instance(opts = {})
  instance = Class.new(@base_parent)
  instance.configuration = Grape::Util::EndpointConfiguration.new(opts[:configuration] || {})
  instance.base = self
  replay_setup_on(instance)
  instance
end

def mounted_instances

def mounted_instances
  instances - [base_instance]
end

def never_mounted?

def never_mounted?
  mounted_instances.empty?
end

def new(...)

Rather than initializing an object of type Grape::API, create an object of type Instance
def new(...)
  base_instance.new(...)
end

def override_all_methods!

Redefines all methods so that are forwarded to add_setup and be recorded
def override_all_methods!
  (base_instance.methods - Class.methods - NON_OVERRIDABLE).each do |method_override|
    define_singleton_method(method_override) do |*args, &block|
      add_setup(method_override, *args, &block)
    end
  end
end

def replay_setup_on(instance)

on classes that inherit from Grape::API
Replays the set up to produce an API as defined in this class, can be called
def replay_setup_on(instance)
  @setup.each do |setup_step|
    replay_step_on(instance, setup_step)
  end
end

def replay_step_on(instance, setup_step)

def replay_step_on(instance, setup_step)
  return if skip_immediate_run?(instance, setup_step[:args])
  args = evaluate_arguments(instance.configuration, *setup_step[:args])
  response = instance.send(setup_step[:method], *args, &setup_step[:block])
  if skip_immediate_run?(instance, [response])
    response
  else
    evaluate_arguments(instance.configuration, response).first
  end
end

def respond_to?(method, include_private = false)

def respond_to?(method, include_private = false)
  super || base_instance.respond_to?(method, include_private)
end

def respond_to_missing?(method, include_private = false)

def respond_to_missing?(method, include_private = false)
  base_instance.respond_to?(method, include_private)
end

def skip_immediate_run?(instance, args)

Skips steps that contain arguments to be lazily executed (on re-mount time)
def skip_immediate_run?(instance, args)
  instance.base_instance? &&
    (any_lazy?(args) || args.any? { |arg| arg.is_a?(Hash) && any_lazy?(arg.values) })
end