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