From 1147658d9136da0c23b2f6c4516b46536c5322b9 Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sun, 11 Jun 2023 15:46:34 +0200 Subject: [PATCH] Fix custom validator not ending with _validator (#2337) * Remove ! Add spec * Changelog entry * Update Changelog's entry Update spec comment Add spec for anonymous class * Fix cop --- CHANGELOG.md | 1 + lib/grape/validations/validators/base.rb | 2 +- .../grape/validations/validators/base_spec.rb | 38 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 spec/grape/validations/validators/base_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index eaf3316295..23a01a2117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ #### Fixes * [#2328](https://github.com/ruby-grape/grape/pull/2328): Don't cache Class.instance_methods - [@byroot](https://github.com/byroot). +* [#2337](https://github.com/ruby-grape/grape/pull/2337): Fix: allow custom validators that do not end with _validator - [@ericproulx](https://github.com/ericproulx). * Your contribution here. ## 1.7.1 (2023/05/14) diff --git a/lib/grape/validations/validators/base.rb b/lib/grape/validations/validators/base.rb index c720d793c2..cfa49155ef 100644 --- a/lib/grape/validations/validators/base.rb +++ b/lib/grape/validations/validators/base.rb @@ -64,7 +64,7 @@ def validate!(params) def self.inherited(klass) return if klass.name.blank? - short_validator_name = klass.name.demodulize.underscore.delete_suffix!('_validator') + short_validator_name = klass.name.demodulize.underscore.delete_suffix('_validator') Validations.register_validator(short_validator_name, klass) end diff --git a/spec/grape/validations/validators/base_spec.rb b/spec/grape/validations/validators/base_spec.rb new file mode 100644 index 0000000000..9f1ff97601 --- /dev/null +++ b/spec/grape/validations/validators/base_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +RSpec.describe Grape::Validations::Validators::Base do + describe '#inherited' do + context 'when validator is anonymous' do + subject(:custom_validator) { Class.new(described_class) } + + it 'does not register the validator' do + expect(Grape::Validations).not_to receive(:register_validator) + custom_validator + end + end + + # Anonymous class does not have a name and class A < B would leak. + # Simulates inherited callback + context "when validator's underscored name does not end with _validator" do + subject(:custom_validator) { described_class.inherited(TestModule::CustomValidatorABC) } + + before { stub_const('TestModule::CustomValidatorABC', Class.new) } + + it 'registers the custom validator with a short name' do + expect(Grape::Validations).to receive(:register_validator).with('custom_validator_abc', TestModule::CustomValidatorABC) + custom_validator + end + end + + context "when validator's underscored name ends with _validator" do + subject(:custom_validator) { described_class.inherited(TestModule::CustomValidator) } + + before { stub_const('TestModule::CustomValidator', Class.new) } + + it 'registers the custom validator with short name not ending with validator' do + expect(Grape::Validations).to receive(:register_validator).with('custom', TestModule::CustomValidator) + custom_validator + end + end + end +end