From 63534f3b21fe96f886d7648afc016176ea6a81db Mon Sep 17 00:00:00 2001 From: OuYangJinTing Date: Tue, 9 Jul 2024 11:24:34 +0800 Subject: [PATCH] Support allow `nil` in `length` validator --- CHANGELOG.md | 1 + README.md | 5 ++-- lib/grape/locale/en.yml | 1 + .../validators/length_validator.rb | 7 +++++ .../validations/validators/length_spec.rb | 29 +++++++++++++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 634a172f9b..1be187b3c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ #### Features +* [#2464](https://github.com/ruby-grape/grape/pull/2464): Support allow `nil` in `length` validator - [@OuYangJinTing](https://github.com/OuYangJinTing). * Your contribution here. #### Fixes diff --git a/README.md b/README.md index 3be2dcead9..a1bd6b4df4 100644 --- a/README.md +++ b/README.md @@ -1714,12 +1714,13 @@ end 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. +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 need to allow `nil` value, must to pass the `allow_nil: true` option. ```ruby params do requires :str, type: String, length: { min: 3 } - requires :list, type: [Integer], length: { min: 3, max: 5 } + requires :list, type: [Integer], length: { min: 3, max: 5, allow_nil: true } requires :hash, type: Hash, length: { max: 5 } end ``` diff --git a/lib/grape/locale/en.yml b/lib/grape/locale/en.yml index 3ed7bcc3ab..f7bd366247 100644 --- a/lib/grape/locale/en.yml +++ b/lib/grape/locale/en.yml @@ -7,6 +7,7 @@ en: presence: 'is missing' regexp: 'is invalid' blank: 'is empty' + nil: 'is nil' values: 'does not have a valid value' except_values: 'has a value not allowed' same_as: 'is not the same as %{parameter}' diff --git a/lib/grape/validations/validators/length_validator.rb b/lib/grape/validations/validators/length_validator.rb index bcd0c95592..c070cbc60d 100644 --- a/lib/grape/validations/validators/length_validator.rb +++ b/lib/grape/validations/validators/length_validator.rb @@ -7,6 +7,7 @@ class LengthValidator < Base def initialize(attrs, options, required, scope, **opts) @min = options[:min] @max = options[:max] + @allow_nil = options[:allow_nil] super @@ -18,6 +19,12 @@ def initialize(attrs, options, required, scope, **opts) def validate_param!(attr_name, params) param = params[attr_name] + if param.nil? + return if @allow_nil + + raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message(:nil)) + end + 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..4c012d4f72 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: 0, allow_nil: true } + end + post 'allow_nil_param' do + end + + params do + requires :list, type: [Integer], length: { min: 0, allow_nil: false } + end + post 'disallow_nil_param' do + end + params do requires :list, type: [Integer], length: { min: 2, message: 'not match' } end @@ -187,6 +199,23 @@ end end + describe 'when a nil value is passed' do + context '/allow_nil_param' do + it do + post '/allow_nil_param', list: nil + expect(last_response.status).to eq(201) + end + end + + context '/disallow_nil_param' do + it do + post '/disallow_nil_param', list: nil + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('list is nil') + end + end + end + describe '/type_is_not_array' do context 'raises an error' do it do