From 2efbd0116b3ef69cdafdd5edba9412ed91fdfe63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Glauco=20Cust=C3=B3dio?= Date: Mon, 17 Dec 2018 12:27:25 +0000 Subject: [PATCH] Add same_as validator --- CHANGELOG.md | 1 + README.md | 22 +++++++ lib/grape.rb | 1 + lib/grape/locale/en.yml | 1 + lib/grape/validations/validators/same_as.rb | 23 +++++++ .../validations/validators/same_as_spec.rb | 63 +++++++++++++++++++ spec/spec_helper.rb | 1 + 7 files changed, 112 insertions(+) create mode 100644 lib/grape/validations/validators/same_as.rb create mode 100644 spec/grape/validations/validators/same_as_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 540f7495d5..ffbdac6ed2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ #### Features * Your contribution here. +* [#1850](https://github.com/ruby-grape/grape/pull/1850): Adds `same_as` validator - [@glaucocustodio](https://github.com/glaucocustodio). * [#1833](https://github.com/ruby-grape/grape/pull/1833): Allows to set the `ParamBuilder` globally - [@myxoh](https://github.com/myxoh). * [#1844](https://github.com/ruby-grape/grape/pull/1844): Fix: enforce `:tempfile` to be a `Tempfile` object in `File` validator - [@Nyangawa](https://github.com/Nyangawa). diff --git a/README.md b/README.md index 6d0d6721a1..317df4e194 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ - [allow_blank](#allow_blank) - [values](#values) - [except_values](#except_values) + - [same_as](#same_as) - [regexp](#regexp) - [mutually_exclusive](#mutually_exclusive) - [exactly_one_of](#exactly_one_of) @@ -62,6 +63,7 @@ - [I18n](#i18n) - [Custom Validation messages](#custom-validation-messages) - [presence, allow_blank, values, regexp](#presence-allow_blank-values-regexp) + - [same_as](#same_as-1) - [all_or_none_of](#all_or_none_of-1) - [mutually_exclusive](#mutually_exclusive-1) - [exactly_one_of](#exactly_one_of-1) @@ -1351,6 +1353,17 @@ params do end ``` +#### `same_as` + +A `same_as` option can be given to ensure that values of parameters match. + +```ruby +params do + requires :password + requires :password_confirmation, same_as: :password +end +``` + #### `regexp` Parameters can be restricted to match a specific regular expression with the `:regexp` option. If the value @@ -1663,6 +1676,15 @@ params do end ``` +#### `same_as` + +```ruby +params do + requires :password + requires :password_confirmation, same_as: { value: :password, message: 'not match' } +end +``` + #### `all_or_none_of` ```ruby diff --git a/lib/grape.rb b/lib/grape.rb index 90597562d3..9cfcfcecab 100644 --- a/lib/grape.rb +++ b/lib/grape.rb @@ -207,6 +207,7 @@ module ServeFile require 'grape/validations/validators/mutual_exclusion' require 'grape/validations/validators/presence' require 'grape/validations/validators/regexp' +require 'grape/validations/validators/same_as' require 'grape/validations/validators/values' require 'grape/validations/validators/except_values' require 'grape/validations/params_scope' diff --git a/lib/grape/locale/en.yml b/lib/grape/locale/en.yml index 7ebfa97fc9..10fa381f7d 100644 --- a/lib/grape/locale/en.yml +++ b/lib/grape/locale/en.yml @@ -9,6 +9,7 @@ en: blank: 'is empty' values: 'does not have a valid value' except_values: 'has a value not allowed' + same_as: 'is not the same as %{parameter}' missing_vendor_option: problem: 'missing :vendor option.' summary: 'when version using header, you must specify :vendor option. ' diff --git a/lib/grape/validations/validators/same_as.rb b/lib/grape/validations/validators/same_as.rb new file mode 100644 index 0000000000..126ba3f4de --- /dev/null +++ b/lib/grape/validations/validators/same_as.rb @@ -0,0 +1,23 @@ +module Grape + module Validations + class SameAsValidator < Base + def validate_param!(attr_name, params) + confirmation = options_key?(:value) ? @option[:value] : @option + return if params[attr_name] == params[confirmation] + raise Grape::Exceptions::Validation, + params: [@scope.full_name(attr_name)], + message: build_message + end + + private + + def build_message + if options_key?(:message) + @option[:message] + else + format I18n.t(:same_as, scope: 'grape.errors.messages'), parameter: @option + end + end + end + end +end diff --git a/spec/grape/validations/validators/same_as_spec.rb b/spec/grape/validations/validators/same_as_spec.rb new file mode 100644 index 0000000000..37f10fc454 --- /dev/null +++ b/spec/grape/validations/validators/same_as_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe Grape::Validations::SameAsValidator do + module ValidationsSpec + module SameAsValidatorSpec + class API < Grape::API + params do + requires :password + requires :password_confirmation, same_as: :password + end + post do + end + + params do + requires :password + requires :password_confirmation, same_as: { value: :password, message: 'not match' } + end + post '/custom-message' do + end + end + end + end + + def app + ValidationsSpec::SameAsValidatorSpec::API + end + + describe '/' do + context 'is the same' do + it do + post '/', password: '987654', password_confirmation: '987654' + expect(last_response.status).to eq(201) + expect(last_response.body).to eq('') + end + end + + context 'is not the same' do + it do + post '/', password: '123456', password_confirmation: 'whatever' + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('password_confirmation is not the same as password') + end + end + end + + describe '/custom-message' do + context 'is the same' do + it do + post '/custom-message', password: '987654', password_confirmation: '987654' + expect(last_response.status).to eq(201) + expect(last_response.body).to eq('') + end + end + + context 'is not the same' do + it do + post '/custom-message', password: '123456', password_confirmation: 'whatever' + expect(last_response.status).to eq(400) + expect(last_response.body).to eq('password_confirmation not match') + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9baf9bf57c..1653756ad6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -20,6 +20,7 @@ config.include Rack::Test::Methods config.include Spec::Support::Helpers config.raise_errors_for_deprecations! + config.filter_run_when_matching :focus config.before(:each) { Grape::Util::InheritableSetting.reset_global! } end