From 5f6c27970f1579126a9cb9576e2396bea635ab4d Mon Sep 17 00:00:00 2001 From: OuYangJinTing Date: Mon, 8 Jul 2024 21:54:37 +0800 Subject: [PATCH] Support allow `nil` in `length` validator --- CHANGELOG.md | 11 +++++++ README.md | 8 +++-- lib/grape/locale/en.yml | 1 + .../validators/length_validator.rb | 7 +++++ lib/grape/version.rb | 2 +- .../validations/validators/length_spec.rb | 29 +++++++++++++++++++ 6 files changed, 54 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c203f8de..423e6a3121 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +### 2.2.0 (Next) + +#### 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 + +* Your contribution here. + ### 2.1.2 (2024-06-28) #### Fixes diff --git a/README.md b/README.md index 6f568149d8..4f5fd76e63 100644 --- a/README.md +++ b/README.md @@ -157,8 +157,9 @@ Grape is a REST-like API framework for Ruby. It's designed to run on Rack or com ## Stable Release -You're reading the documentation for the stable release of Grape, **2.1.2**. +You're reading the documentation for the next release of Grape, which should be 2.2.0. Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version. +The current stable release is [2.1.2](https://github.com/ruby-grape/grape/blob/v2.1.2/README.md). ## Project Resources @@ -1713,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, please 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/lib/grape/version.rb b/lib/grape/version.rb index f3bdb18f85..5083e38bd9 100644 --- a/lib/grape/version.rb +++ b/lib/grape/version.rb @@ -2,5 +2,5 @@ module Grape # The current version of Grape. - VERSION = '2.1.2' + VERSION = '2.2.0' end diff --git a/spec/grape/validations/validators/length_spec.rb b/spec/grape/validations/validators/length_spec.rb index 8fa9f84876..e14c6b5007 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 } + 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