diff --git a/CHANGELOG.md b/CHANGELOG.md index 65adf0bfb7..1c5a3feb85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Next Release * [#525](https://github.com/intridea/grape/pull/525): The default status code returned from `error!` has been changed from 403 to 500 - [@dblock](https://github.com/dblock). * [#526](https://github.com/intridea/grape/pull/526): Allowed specifying headers in `error!` - [@dblock](https://github.com/dblock). * [#527](https://github.com/intridea/grape/pull/527): The `before_validation` callback is now a distinct one - [@myitcv](https://github.com/myitcv). +* [#530](https://github.com/intridea/grape/pull/530): Added ability to restrict `declared(params)` to the local endpoint with `include_parent_namespaces: false` - [@myitcv](https://github.com/myitcv). * [#531](https://github.com/intridea/grape/pull/531): Helpers are now available to auth middleware, executing in the context of the endpoint - [@joelvh](https://github.com/joelvh). * [#540](https://github.com/intridea/grape/pull/540): Ruby 2.1.0 is now supported - [@salimane](https://github.com/salimane). * [#544](https://github.com/intridea/grape/pull/544): The `rescue_from` keyword now handles subclasses of exceptions by default - [@xevix](https://github.com/xevix). diff --git a/lib/grape/endpoint.rb b/lib/grape/endpoint.rb index ccbde50fb2..828652cca3 100644 --- a/lib/grape/endpoint.rb +++ b/lib/grape/endpoint.rb @@ -160,12 +160,20 @@ def call!(env) # A filtering method that will return a hash # consisting only of keys that have been declared by a - # `params` statement. + # `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` and `:stringify` options. - def declared(params, options = {}, declared_params = settings.gather(:declared_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) + if declared_params.nil? + declared_params = !options[:include_parent_namespaces] ? settings[:declared_params] : + settings.gather(:declared_params) + end unless declared_params raise ArgumentError, "Tried to filter for declared parameters but none exist." diff --git a/spec/grape/endpoint_spec.rb b/spec/grape/endpoint_spec.rb index faac50bb20..b225333112 100644 --- a/spec/grape/endpoint_spec.rb +++ b/spec/grape/endpoint_spec.rb @@ -282,6 +282,16 @@ def app declared_params: declared(params) } end + params do + requires :happy + optional :days + end + get '/test' do + { + params: params, + declared_params: declared(params, include_parent_namespaces: false) + } + end end end end @@ -291,7 +301,15 @@ def app expect(last_response.status).to eq 200 json = JSON.parse(last_response.body, symbolize_names: true) expect(json[:params][:id]).to eq 123 - expect(json[:declared_params].keys).to include :foo, :bar, :id + expect(json[:declared_params].keys).to match_array [:foo, :bar, :id] + end + + it 'does not include params defined in the parent namespace with include_parent_namespaces: false' do + get '/something/123/test', happy: 'test', extra: 'hello' + expect(last_response.status).to eq 200 + json = JSON.parse(last_response.body, symbolize_names: true) + expect(json[:params][:id]).to eq 123 + expect(json[:declared_params].keys).to match_array [:happy, :days] end end