lib/grape/dsl/inside_route.rb in grape-0.13.0 vs lib/grape/dsl/inside_route.rb in grape-0.14.0
- old
+ new
@@ -4,61 +4,78 @@
module DSL
module InsideRoute
extend ActiveSupport::Concern
include Grape::DSL::Settings
- # A filtering method that will return a hash
- # consisting only of keys that have been declared by a
- # `params` statement against the current/target endpoint or parent
- # namespaces.
- #
- # @param params [Hash] The initial hash to filter. Usually this will just be `params`
- # @param options [Hash] Can pass `:include_missing`, `:stringify` and `:include_parent_namespaces`
- # options. `:include_parent_namespaces` defaults to true, hence must be set to false if
- # you want only to return params declared against the current/target endpoint.
- def declared(params, options = {}, declared_params = nil)
- options[:include_missing] = true unless options.key?(:include_missing)
- options[:include_parent_namespaces] = true unless options.key?(:include_parent_namespaces)
+ # Denotes a situation where a DSL method has been invoked in a
+ # filter which it should not yet be available in
+ class MethodNotYetAvailable < StandardError; end
- if declared_params.nil?
- declared_params = (!options[:include_parent_namespaces] ? route_setting(:declared_params) :
- (route_setting(:saved_declared_params) || [])).flatten(1) || []
- end
+ # @param type [Symbol] The type of filter for which evaluation has been
+ # completed
+ # @return [Module] A module containing method overrides suitable for the
+ # position in the filter evaluation sequence denoted by +type+. This
+ # defaults to an empty module if no overrides are defined for the given
+ # filter +type+.
+ def self.post_filter_methods(type)
+ @post_filter_modules ||= { before: PostBeforeFilter }
+ @post_filter_modules[type]
+ end
- unless declared_params
- fail ArgumentError, 'Tried to filter for declared parameters but none exist.'
- end
+ # Methods which should not be available in filters until the before filter
+ # has completed
+ module PostBeforeFilter
+ def declared(params, options = {}, declared_params = nil)
+ options = options.reverse_merge(include_missing: true, include_parent_namespaces: true)
- if params.is_a? Array
- params.map do |param|
- declared(param || {}, options, declared_params)
- end
- else
- declared_params.inject(Hashie::Mash.new) do |hash, key|
- key = { key => nil } unless key.is_a? Hash
+ declared_params ||= (!options[:include_parent_namespaces] ? route_setting(:declared_params) : (route_setting(:saved_declared_params) || [])).flatten(1) || []
- key.each_pair do |parent, children|
- output_key = options[:stringify] ? parent.to_s : parent.to_sym
+ fail ArgumentError, 'Tried to filter for declared parameters but none exist.' unless declared_params
- next unless options[:include_missing] || params.key?(parent)
-
- hash[output_key] = if children
- children_params = params[parent] || (children.is_a?(Array) ? [] : {})
- declared(children_params, options, Array(children))
- else
- params[parent]
- end
+ if params.is_a? Array
+ params.map do |param|
+ declared(param || {}, options, declared_params)
end
+ else
+ declared_params.each_with_object(Hashie::Mash.new) do |key, hash|
+ key = { key => nil } unless key.is_a? Hash
- hash
+ key.each_pair do |parent, children|
+ output_key = options[:stringify] ? parent.to_s : parent.to_sym
+
+ next unless options[:include_missing] || params.key?(parent)
+
+ hash[output_key] = if children
+ children_params = params[parent] || (children.is_a?(Array) ? [] : {})
+ declared(children_params, options, Array(children))
+ else
+ params[parent]
+ end
+ end
+ end
end
end
end
+ # A filtering method that will return a hash
+ # consisting only of keys that have been declared by a
+ # `params` statement against the current/target endpoint or parent
+ # namespaces.
+ #
+ # @see +PostBeforeFilter#declared+
+ #
+ # @param params [Hash] The initial hash to filter. Usually this will just be `params`
+ # @param options [Hash] Can pass `:include_missing`, `:stringify` and `:include_parent_namespaces`
+ # options. `:include_parent_namespaces` defaults to true, hence must be set to false if
+ # you want only to return params declared against the current/target endpoint.
+ def declared(*)
+ fail MethodNotYetAvailable, '#declared is not available prior to parameter validation.'
+ end
+
# The API version as specified in the URL.
def version
- env['api.version']
+ env[Grape::Env::API_VERSION]
end
# End the request and display an error to the
# end user with the specified message.
#
@@ -72,23 +89,29 @@
# Redirect to a new url.
#
# @param url [String] The url to be redirect.
# @param options [Hash] The options used when redirect.
# :permanent, default false.
+ # :body, default a short message including the URL.
def redirect(url, options = {})
- merged_options = { permanent: false }.merge(options)
- if merged_options[:permanent]
+ permanent = options.fetch(:permanent, false)
+ body_message = options.fetch(:body, nil)
+ if permanent
status 301
+ body_message ||= "This resource has been moved permanently to #{url}."
else
if env[Grape::Http::Headers::HTTP_VERSION] == 'HTTP/1.1' && request.request_method.to_s.upcase != Grape::Http::Headers::GET
status 303
+ body_message ||= "An alternate resource is located at #{url}."
else
status 302
+ body_message ||= "This resource has been moved temporarily to #{url}."
end
end
header 'Location', url
- body ''
+ content_type 'text/plain'
+ body body_message
end
# Set or retrieve the HTTP status code.
#
# @param status [Integer] The HTTP Status Code to return for this request.
@@ -239,11 +262,11 @@
representation = { root => representation } if root
if key
representation = (@body || {}).merge(key => representation)
elsif entity_class.present? && @body
- fail ArgumentError, "Representation of type #{representation.class} cannot be merged." unless representation.respond_to?('merge')
+ fail ArgumentError, "Representation of type #{representation.class} cannot be merged." unless representation.respond_to?(:merge)
representation = @body.merge(representation)
end
body representation
end
@@ -255,11 +278,11 @@
# desc "Returns the route description."
# get '/' do
# route.route_description
# end
def route
- env['rack.routing_args'][:route_info]
+ env[Grape::Env::RACK_ROUTING_ARGS][:route_info]
end
# Attempt to locate the Entity class for a given object, if not given
# explicitly. This is done by looking for the presence of Klass::Entity,
# where Klass is the class of the `object` parameter, or one of its
@@ -291,10 +314,10 @@
# @return the representation of the given object as done through
# the given entity_class.
def entity_representation_for(entity_class, object, options)
embeds = { env: env }
- embeds[:version] = env['api.version'] if env['api.version']
+ embeds[:version] = env[Grape::Env::API_VERSION] if env[Grape::Env::API_VERSION]
entity_class.represent(object, embeds.merge(options))
end
end
end
end