Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
* [#2733](https://github.com/ruby-grape/grape/pull/2733): Drop the dead `active_support/core_ext/hash/reverse_merge` require; call `ActiveSupport::HashWithIndifferentAccess.new(...)` directly at call sites - [@ericproulx](https://github.com/ericproulx).
* [#2734](https://github.com/ruby-grape/grape/pull/2734): Extract `options_route_enabled` from the Endpoint options Hash into a dedicated `attr_accessor` - [@ericproulx](https://github.com/ericproulx).
* [#2736](https://github.com/ruby-grape/grape/pull/2736): Collapse `Endpoint#run_validators` rescue branches via `ValidationErrors` flatten; `ValidationErrors#initialize` keyword renamed `errors:` → `exceptions:` - [@ericproulx](https://github.com/ericproulx).
* [#2735](https://github.com/ruby-grape/grape/pull/2735): Normalize `Grape::Endpoint#options` into an immutable `Grape::Endpoint::Options` `Data` value object; Hash-style `[]` reads kept for back-compat - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.

#### Fixes
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/dsl/inside_route.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def version
end

def configuration
options[:for].configuration.evaluate
config.for.configuration.evaluate
end

# End the request and display an error to the
Expand Down
25 changes: 13 additions & 12 deletions lib/grape/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Endpoint
# inside route handlers, +before+/+after+/+after_validation+/+finally+
# filters, and +rescue_from+ blocks.
def logger
options[:for].logger
config.for.logger
end

class << self
Expand All @@ -38,7 +38,8 @@ def block_to_unbound_method(block)
# Create a new endpoint.
# @param new_settings [InheritableSetting] settings to determine the params,
# validations, and other properties from.
# @param options [Hash] attributes of this endpoint
# @param options [Hash] attributes of this endpoint, normalized into a
# +Grape::Endpoint::Options+ value object.
# @option options path [String or Array] the path to this endpoint, within
# the current scope.
# @option options method [String or Array] which HTTP method(s) can be used
Expand All @@ -60,18 +61,18 @@ def initialize(new_settings, **options, &block)
inheritable_setting.namespace_inheritable[:default_error_status] ||= 500

@options = options

@options[:path] = Array(@options[:path])
@options[:path] << '/' if @options[:path].empty?
@options[:method] = Array(@options[:method])
@config = Options.new(**options)

@status = nil
@stream = nil
@body = nil
@source = self.class.block_to_unbound_method(block)
@before_filter_passed = false
@options_route_enabled = false
@endpoints = @options[:app].endpoints if @options[:app].respond_to?(:endpoints)
@endpoints = @config.app.endpoints if @config.app.respond_to?(:endpoints)
end

# Update our settings from a given set of stackable parameters. Used when
Expand Down Expand Up @@ -132,7 +133,7 @@ def call!(env)

def ==(other)
other.is_a?(self.class) &&
options == other.options &&
config == other.config &&
inheritable_setting == other.inheritable_setting
end
alias eql? ==
Expand Down Expand Up @@ -220,7 +221,7 @@ def run_filters(filters, type = :other)
end
end

attr_reader :befores, :before_validations, :after_validations, :afters, :finallies
attr_reader :befores, :before_validations, :after_validations, :afters, :finallies, :config

def options?
options_route_enabled && env[Rack::REQUEST_METHOD] == Rack::OPTIONS
Expand All @@ -231,7 +232,7 @@ def options?
attr_reader :before_filter_passed

def compile!
@app = options[:app] || build_stack
@app = config.app || build_stack
@helpers = build_helpers
stackable = inheritable_setting.namespace_stackable
@befores = stackable[:befores]
Expand All @@ -243,20 +244,20 @@ def compile!
end

def to_routes
route_options = options[:route_options]
route_options = config.route_options
default_route_options = prepare_default_route_attributes(route_options)
complete_route_options = route_options.merge(default_route_options)
path_settings = prepare_default_path_settings

options[:method].flat_map do |method|
options[:path].map do |path|
config.http_methods.flat_map do |method|
config.path.map do |path|
prepared_path = Path.new(path, default_route_options[:namespace], path_settings)
pattern = Grape::Router::Pattern.new(
origin: prepared_path.origin,
suffix: prepared_path.suffix,
anchor: default_route_options[:anchor],
params: route_options[:params],
format: options[:format],
format: config.format,
version: default_route_options[:version],
requirements: default_route_options[:requirements]
)
Expand All @@ -273,7 +274,7 @@ def prepare_default_route_attributes(route_options)
prefix: inheritable_setting.namespace_inheritable[:root_prefix],
anchor: route_options.fetch(:anchor, true),
settings: inheritable_setting.route.except(:declared_params, :saved_validations),
forward_match: options[:forward_match]
forward_match: config.forward_match
}
end

Expand Down
19 changes: 19 additions & 0 deletions lib/grape/endpoint/options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module Grape
class Endpoint
# Immutable value object holding the keyword inputs passed to
# +Grape::Endpoint.new+. Internal to {Grape::Endpoint}, which builds it
# from the +**options+ Hash in #initialize so the public +options+ reader
# stays a plain Hash for downstream gems (e.g. grape-swagger).
# +:method+ is renamed to +:http_methods+ on the value object to avoid
# shadowing +Object#method+ via the generated Data accessor.
Options = Data.define(:path, :http_methods, :for, :route_options, :app, :format, :forward_match) do
def initialize(path:, method:, route_options: {}, app: nil, format: nil, forward_match: nil, **rest)
path = Array(path)
path << '/' if path.empty?
super(path:, http_methods: Array(method), route_options:, app:, format:, forward_match:, **rest)
end
end
end
end
Loading