diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6527392..c9df0a2 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -28,7 +28,7 @@ Metrics/AbcSize: # Offense count: 3 # Configuration parameters: CountComments. Metrics/ClassLength: - Max: 209 + Max: 216 # Offense count: 10 Metrics/CyclomaticComplexity: diff --git a/CHANGELOG.md b/CHANGELOG.md index a4e2642..b6efa06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ #### Features * [#448](https://github.com/ruby-grape/grape-swagger/pull/448): Header parameters are now prepended to the parameter list - [@anakinj](https://github.com/anakinj). -* [#444](https://github.com/ruby-grape/grape-swagger/pull/444): With multi types parameter the first type is use as the documentation type [@scauglog](https://github.com/scauglog). +* [#444](https://github.com/ruby-grape/grape-swagger/pull/444): With multi types parameter the first type is use as the documentation type - [@scauglog](https://github.com/scauglog). +* [#463](https://github.com/ruby-grape/grape-swagger/pull/463): Added 'hidden' option for parameter to be exclude from generated documentation - [@anakinj](https://github.com/anakinj). * Your contribution here. #### Fixes diff --git a/Gemfile b/Gemfile index fa92707..fde4e4b 100644 --- a/Gemfile +++ b/Gemfile @@ -10,3 +10,8 @@ else end gem ENV['MODEL_PARSER'] if ENV.key?('MODEL_PARSER') + +if RUBY_VERSION < '2.2.2' + gem 'rack', '<2.0.0' + gem 'activesupport', '<5.0.0' +end diff --git a/README.md b/README.md index 5667a04..4723abf 100644 --- a/README.md +++ b/README.md @@ -351,6 +351,7 @@ add_swagger_documentation \ * [Overriding param type](#overriding-param-type) * [Overriding type](#overriding-type) * [Multi types](#multi-types) +* [Hiding parameters](#hiding-parameters) * [Response documentation](#response) @@ -528,6 +529,20 @@ end } ``` +#### Hiding parameters + +Exclude single optional parameter from the documentation + +```ruby +params do + optional :one, documentation: { hidden: true } + optional :two, documentation: { hidden: -> { true } } +end +post :act do + ... +end +``` + #### Overriding the route summary By default, the route summary is filled with the value supplied to `desc`. diff --git a/lib/grape-swagger/endpoint.rb b/lib/grape-swagger/endpoint.rb index c315cae..ed9f057 100644 --- a/lib/grape-swagger/endpoint.rb +++ b/lib/grape-swagger/endpoint.rb @@ -221,13 +221,13 @@ module Grape end end - def parse_request_params(required) + def parse_request_params(params) array_key = nil - required.each_with_object({}) do |param, memo| - array_key = param.first.to_s if param_type_is_array?(param.last[:type]) - - param.last[:is_array] = true if array_key && param.first.start_with?(array_key) - memo[param.first] = param.last unless (param.last[:type] == 'Hash' || param.last[:type] == 'Array') && !param.last.key?(:documentation) + params.select { |param| public_parameter?(param) }.each_with_object({}) do |param, memo| + name, options = *param + array_key = name.to_s if param_type_is_array?(options[:type]) + options[:is_array] = true if array_key && name.start_with?(array_key) + memo[param.first] = options unless (options[:type] == 'Hash' || options[:type] == 'Array') && !options.key?(:documentation) end end @@ -274,5 +274,13 @@ module Grape route_hidden = route_hidden.call if route_hidden.is_a?(Proc) route_hidden end + + def public_parameter?(param) + param_options = param.last + return true unless param_options.key?(:documentation) && !param_options[:required] + param_hidden = param_options[:documentation].fetch(:hidden, false) + param_hidden = param_hidden.call if param_hidden.is_a?(Proc) + !param_hidden + end end end diff --git a/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb b/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb new file mode 100644 index 0000000..b30a6f3 --- /dev/null +++ b/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb @@ -0,0 +1,90 @@ +require 'spec_helper' + +describe 'hidden flag enables a single endpoint parameter to be excluded from the documentation' do + include_context "#{MODEL_PARSER} swagger example" + before :all do + module TheApi + class HideParamsApi < Grape::API + namespace :flat_params_endpoint do + desc 'This is a endpoint with a flat parameter hierarchy' + params do + requires :name, type: String, documentation: { desc: 'name' } + optional :favourite_color, type: String, documentation: { desc: 'I should not be anywhere', hidden: true } + optional :proc_param, type: String, documentation: { desc: 'I should not be anywhere', hidden: -> { true } } + end + + post do + { 'declared_params' => declared(params) } + end + end + + namespace :nested_params_endpoint do + desc 'This is a endpoint with a nested parameter hierarchy' + params do + optional :name, type: String, documentation: { desc: 'name' } + optional :hidden_attribute, type: Hash do + optional :favourite_color, type: String, documentation: { desc: 'I should not be anywhere', hidden: true } + end + + optional :attributes, type: Hash do + optional :attribute_1, type: String, documentation: { desc: 'Attribute one' } + optional :hidden_attribute, type: String, documentation: { desc: 'I should not be anywhere', hidden: true } + end + end + + post do + { 'declared_params' => declared(params) } + end + end + + namespace :required_param_endpoint do + desc 'This endpoint has hidden defined for a required parameter' + params do + requires :name, type: String, documentation: { desc: 'name', hidden: true } + end + + post do + { 'declared_params' => declared(params) } + end + end + + add_swagger_documentation + end + end + end + + let(:app) { TheApi::HideParamsApi } + + describe 'simple flat parameter hierarchy' do + subject do + get '/swagger_doc/flat_params_endpoint' + JSON.parse(last_response.body) + end + + specify do + expect(subject['paths']['/flat_params_endpoint']['post']['parameters'].map { |p| p['name'] }).not_to include('favourite_color', 'proc_param') + end + end + + describe 'nested parameter hierarchy' do + subject do + get '/swagger_doc/nested_params_endpoint' + JSON.parse(last_response.body) + end + + specify do + expect(subject['paths']['/nested_params_endpoint']['post']['parameters'].map { |p| p['name'] }).not_to include(/hidden_attribute/) + end + end + + describe 'hidden defined for required parameter' do + subject do + get '/swagger_doc/required_param_endpoint' + JSON.parse(last_response.body) + end + + specify do + expect(subject['paths']['/required_param_endpoint']['post']['parameters'].map { |p| p['name'] }).to include('name') + end + end +end