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 @@ -20,6 +20,7 @@
* [#2786](https://github.com/ruby-grape/grape/pull/2786): Make route `requirements` and `anchor` explicit keyword arguments and first-class endpoint inputs instead of opaque `route_options` keys - [@ericproulx](https://github.com/ericproulx).
* [#2788](https://github.com/ruby-grape/grape/pull/2788): Compare the base API instead of `to_s` when refreshing a mounted app - [@ericproulx](https://github.com/ericproulx).
* [#2796](https://github.com/ruby-grape/grape/pull/2796): Remove `Grape::Util::ReverseStackableValues`, storing rescue handlers in plain per-scope hashes merged over `InheritableSetting#parent` - [@ericproulx](https://github.com/ericproulx).
* [#2804](https://github.com/ruby-grape/grape/pull/2804): Internalize contract key maps behind `Grape::Util::InheritableSetting` accessors (`contract_key_maps` / `add_contract_key_map`) - [@ericproulx](https://github.com/ericproulx).
* Your contribution here.

#### Fixes
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ A route's declared params were previously carried inside the `route_options` bag

Like `params` above, a route's `requirements` and `anchor` were previously carried inside the `route_options` bag. They are now composed into their own endpoint inputs (`Grape::Endpoint::Options` gains `:requirements` and `:anchor` members, and `Grape::Endpoint.new` gains `requirements:` and `anchor:` keywords) and exposed only through the `route.requirements` and `route.anchor` readers. `route.options[:requirements]` and `route.options[:anchor]` now return `nil` — including for a mount's `anchor: false`. Nothing in Grape or grape-swagger read them that way, so this only affects code that reached into the options Hash for these keys directly.

#### Contract key maps are recorded through `InheritableSetting` accessors

The Dry::Schema key maps registered by `contract` blocks are now recorded and read through dedicated accessors on `Grape::Util::InheritableSetting` (`contract_key_maps` / `add_contract_key_map(key_map)`) instead of the raw `namespace_stackable[:contract_key_map]` key, following the same move made for rescue handlers. The key's storage is unchanged for now, so `namespace_stackable[:contract_key_map]` still returns the same values, but it should be considered internal.

### Upgrading to >= 3.3

#### Minimum required Ruby is now 3.3
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/dsl/declared.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def initialize(msg = '#declared is not available prior to parameter validation')
def declared(passed_params, include_parent_namespaces: true, include_missing: true, evaluate_given: false, stringify: false)
raise MethodNotYetAvailable unless before_filter_passed

contract_key_map = inheritable_setting.namespace_stackable[:contract_key_map]
contract_key_map = inheritable_setting.contract_key_maps
handler = DeclaredParamsHandler.new(include_missing:, evaluate_given:, stringify:, contract_key_map:)
declared_params = include_parent_namespaces ? inheritable_setting.route[:declared_params] : (inheritable_setting.namespace_stackable[:declared_params].last || [])
renamed_params = inheritable_setting.route[:renamed_params] || {}
Expand Down
13 changes: 13 additions & 0 deletions lib/grape/util/inheritable_setting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ def namespace_stackable_with_hash(key)
data.each_with_object({}) { |value, result| result.deep_merge!(value) }
end

# Dry::Schema key maps registered by +contract+ blocks (see
# Validations::ContractScope), one per contract, outermost scope first;
# +declared+ uses them to write coerced params back under their
# declared keys. Record them with #add_contract_key_map; the backing
# store is an internal detail.
def contract_key_maps
namespace_stackable[:contract_key_map]
end

def add_contract_key_map(key_map)
namespace_stackable[:contract_key_map] = key_map
end

# Rescue-handler maps registered by +rescue_from+, keyed by exception
# class and merged so a nested scope's handler wins. Record them with
# #add_rescue_handlers; the backing store is an internal detail.
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/validations/contract_scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def initialize(api, contract = nil, &block)
key_map = contract.key_map
end

api.inheritable_setting.namespace_stackable[:contract_key_map] = key_map
api.inheritable_setting.add_contract_key_map(key_map)
api.inheritable_setting.namespace_stackable[:validations] = Validators::ContractScopeValidator.new(schema: contract)
end
end
Expand Down
Loading