diff --git a/CHANGELOG.md b/CHANGELOG.md index 634a172f9b..55dab475b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### Features +* [#2464](https://github.com/ruby-grape/grape/pull/2464): Allow `nil` in `length` validator - [@OuYangJinTing](https://github.com/OuYangJinTing). * Your contribution here. #### Fixes diff --git a/README.md b/README.md index 3be2dcead9..eda2927e47 100644 --- a/README.md +++ b/README.md @@ -1713,8 +1713,8 @@ end #### `length` Parameters with types that support `#length` method can be restricted to have a specific length with the `:length` option. - -The validator accepts `:min` or `:max` or both options to validate that the value of the parameter is within the given limits. +In addition, if the received parameter value is `nil`, the length validation will not be triggered. +If you want to reject `nil`, you can use the `allow_blank: false` option (This will also reject empty strings). ```ruby params do diff --git a/lib/grape/validations/validators/length_validator.rb b/lib/grape/validations/validators/length_validator.rb index bcd0c95592..78ea580988 100644 --- a/lib/grape/validations/validators/length_validator.rb +++ b/lib/grape/validations/validators/length_validator.rb @@ -18,6 +18,8 @@ def initialize(attrs, options, required, scope, **opts) def validate_param!(attr_name, params) param = params[attr_name] + return if param.nil? + raise ArgumentError, "parameter #{param} does not support #length" unless param.respond_to?(:length) return unless (!@min.nil? && param.length < @min) || (!@max.nil? && param.length > @max) diff --git a/spec/grape/validations/validators/length_spec.rb b/spec/grape/validations/validators/length_spec.rb index 8fa9f84876..0eef2d4586 100644 --- a/spec/grape/validations/validators/length_spec.rb +++ b/spec/grape/validations/validators/length_spec.rb @@ -81,6 +81,18 @@ post 'zero_max' do end + params do + requires :list, type: [Integer], length: { min: 2 } + end + post 'nil_param' do + end + + params do + requires :list, type: [Integer], length: { min: 2 }, allow_blank: false + end + post 'length_with_disallow_blank' do + end + params do requires :list, type: [Integer], length: { min: 2, message: 'not match' } end @@ -187,6 +199,42 @@ end end + describe '/nil_param' do + context 'does not raise an error' do + it do + expect do + post '/nil_param', list: nil + end.not_to raise_error + end + end + end + + describe '/length_with_disallow_blank' do + context 'when length is within limits' do + it do + post '/length_with_disallow_blank', list: [1, 2] + expect(last_response.status).to eq(201) + expect(last_response.body).to eq('') + end + end + + context 'when a nil value is passed' do + it do + post '/length_with_disallow_blank', list: nil + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('list is empty') + end + end + + context 'when a empty string is passed' do + it do + post '/length_with_disallow_blank', list: '' + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('list is expected to have length greater than or equal to 2, list is empty') + end + end + end + describe '/type_is_not_array' do context 'raises an error' do it do