lib/grape/api.rb in grape-1.2.4 vs lib/grape/api.rb in grape-1.2.5
- old
+ new
@@ -4,11 +4,11 @@
module Grape
# The API class is the primary entry point for creating Grape APIs. Users
# should subclass this class in order to build an API.
class API
# Class methods that we want to call on the API rather than on the API object
- NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration]).freeze
+ NON_OVERRIDABLE = (Class.new.methods + %i[call call! configuration compile!]).freeze
class << self
attr_accessor :base_instance, :instances
# Rather than initializing an object of type Grape::API, create an object of type Instance
@@ -40,17 +40,32 @@
add_setup(method_override, *args, &block)
end
end
end
+ # Configure an API from the outside. If a block is given, it'll pass a
+ # configuration hash to the block which you can use to configure your
+ # API. If no block is given, returns the configuration hash.
+ # The configuration set here is accessible from inside an API with
+ # `configuration` as normal.
+ def configure
+ config = @base_instance.configuration
+ if block_given?
+ yield config
+ self
+ else
+ config
+ end
+ end
+
# This is the interface point between Rack and Grape; it accepts a request
# from Rack and ultimately returns an array of three values: the status,
# the headers, and the body. See [the rack specification]
# (http://www.rubydoc.info/github/rack/rack/master/file/SPEC) for more.
# NOTE: This will only be called on an API directly mounted on RACK
def call(*args, &block)
- base_instance.call(*args, &block)
+ instance_for_rack.call(*args, &block)
end
# Allows an API to itself be inheritable:
def make_inheritable(api)
# When a child API inherits from a parent API.
@@ -104,12 +119,25 @@
else
super
end
end
+ def compile!
+ require 'grape/eager_load'
+ instance_for_rack.compile! # See API::Instance.compile!
+ end
+
private
+ def instance_for_rack
+ if never_mounted?
+ base_instance
+ else
+ mounted_instances.first
+ end
+ end
+
# 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
@@ -119,11 +147,17 @@
last_response
end
def replay_step_on(instance, setup_step)
return if skip_immediate_run?(instance, setup_step[:args])
- instance.send(setup_step[:method], *evaluate_arguments(instance.configuration, *setup_step[:args]), &setup_step[:block])
+ 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
# Skips steps that contain arguments to be lazily executed (on re-mount time)
def skip_immediate_run?(instance, args)
instance.base_instance? &&
@@ -135,18 +169,26 @@
end
def evaluate_arguments(configuration, *args)
args.map do |argument|
if argument.respond_to?(:lazy?) && argument.lazy?
- configuration.fetch(argument.access_keys).evaluate
+ argument.evaluate_from(configuration)
elsif argument.is_a?(Hash)
argument.map { |key, value| [key, evaluate_arguments(configuration, value).first] }.to_h
elsif argument.is_a?(Array)
evaluate_arguments(configuration, *argument)
else
argument
end
end
+ end
+
+ def never_mounted?
+ mounted_instances.empty?
+ end
+
+ def mounted_instances
+ instances - [base_instance]
end
end
end
end