diff --git a/lib/active_storage_validations/matchers/concerns/validatable.rb b/lib/active_storage_validations/matchers/concerns/validatable.rb index b3b0fa2..3067a7e 100644 --- a/lib/active_storage_validations/matchers/concerns/validatable.rb +++ b/lib/active_storage_validations/matchers/concerns/validatable.rb @@ -26,7 +26,7 @@ def is_valid? def available_errors [ *validator_class::ERROR_TYPES, - *error_from_custom_message + *errors_from_custom_messages ].compact end @@ -40,8 +40,12 @@ def attribute_validator end end - def error_from_custom_message - attribute_validator.options[:message] + def errors_from_custom_messages + # TODO: Refacto attribute_validator with this logic and make sure it + # works for contextable + @subject.class.validators_on(@attribute_name).filter_map do |validator| + validator.options[:message] if validator.class == validator_class + end end end end diff --git a/test/dummy/app/models/aspect_ratio/matcher.rb b/test/dummy/app/models/aspect_ratio/matcher.rb index 1cb98dc..83cebba 100644 --- a/test/dummy/app/models/aspect_ratio/matcher.rb +++ b/test/dummy/app/models/aspect_ratio/matcher.rb @@ -11,6 +11,8 @@ # class AspectRatio::Matcher < ApplicationRecord + include Validatable + ActiveStorageValidations::AspectRatioValidator::NAMED_ASPECT_RATIOS.each do |aspect_ratio| has_one_attached :"allowing_one_#{aspect_ratio}" validates :"allowing_one_#{aspect_ratio}", aspect_ratio: aspect_ratio @@ -32,6 +34,10 @@ class AspectRatio::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, aspect_ratio: :square + has_one_attached :validatable_different_error_messages + validates :validatable_different_error_messages, aspect_ratio: { with: :portrait, message: 'Custom message 1' }, if: :title_is_quo_vadis? + validates :validatable_different_error_messages, aspect_ratio: { with: :square, message: 'Custom message 2' }, if: :title_is_american_psycho? + has_one_attached :failure_message validates :failure_message, aspect_ratio: :square has_one_attached :failure_message_when_negated diff --git a/test/dummy/app/models/attached/matcher.rb b/test/dummy/app/models/attached/matcher.rb index 77be774..7f4a60c 100644 --- a/test/dummy/app/models/attached/matcher.rb +++ b/test/dummy/app/models/attached/matcher.rb @@ -11,6 +11,8 @@ # class Attached::Matcher < ApplicationRecord + include Validatable + has_one_attached :required validates :required, attached: true @@ -25,6 +27,10 @@ class Attached::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, attached: true + has_one_attached :validatable_different_error_messages + validates :validatable_different_error_messages, attached: { message: 'Custom message 1' }, if: :title_is_quo_vadis? + validates :validatable_different_error_messages, attached: { message: 'Custom message 2' }, if: :title_is_american_psycho? + has_one_attached :failure_message validates :failure_message, attached: true has_one_attached :failure_message_when_negated diff --git a/test/dummy/app/models/concerns/validatable.rb b/test/dummy/app/models/concerns/validatable.rb new file mode 100644 index 0000000..40ce9a0 --- /dev/null +++ b/test/dummy/app/models/concerns/validatable.rb @@ -0,0 +1,17 @@ +module Validatable + extend ActiveSupport::Concern + + private + + def title_is_quo_vadis? + return false if self.title.blank? + + self.title == "Quo vadis" + end + + def title_is_american_psycho? + return false if self.title.blank? + + self.title == "American Psycho" + end +end diff --git a/test/dummy/app/models/content_type/matcher.rb b/test/dummy/app/models/content_type/matcher.rb index 413e545..175d96f 100644 --- a/test/dummy/app/models/content_type/matcher.rb +++ b/test/dummy/app/models/content_type/matcher.rb @@ -11,6 +11,8 @@ # class ContentType::Matcher < ApplicationRecord + include Validatable + has_one_attached :allowing_one validates :allowing_one, content_type: :png has_one_attached :allowing_several @@ -32,6 +34,10 @@ class ContentType::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, content_type: :png + has_one_attached :validatable_different_error_messages + validates :validatable_different_error_messages, content_type: { with: :pdf, message: 'Custom message 1' }, if: :title_is_quo_vadis? + validates :validatable_different_error_messages, content_type: { with: :png, message: 'Custom message 2' }, if: :title_is_american_psycho? + has_one_attached :failure_message validates :failure_message, content_type: :png has_one_attached :failure_message_when_negated diff --git a/test/dummy/app/models/dimension/matcher.rb b/test/dummy/app/models/dimension/matcher.rb index 268ae44..b3dabef 100644 --- a/test/dummy/app/models/dimension/matcher.rb +++ b/test/dummy/app/models/dimension/matcher.rb @@ -11,6 +11,8 @@ # class Dimension::Matcher < ApplicationRecord + include Validatable + %i(width height).each do |dimension| has_one_attached :"#{dimension}_exact" has_one_attached :"#{dimension}_in" @@ -57,6 +59,10 @@ class Dimension::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, dimension: { width: 150, height: 150 } + has_one_attached :validatable_different_error_messages + validates :validatable_different_error_messages, dimension: { width: 150, message: 'Custom message 1' }, if: :title_is_quo_vadis? + validates :validatable_different_error_messages, dimension: { width: 150, message: 'Custom message 2' }, if: :title_is_american_psycho? + has_one_attached :failure_message validates :failure_message, dimension: { width: 150, height: 150 } has_one_attached :failure_message_when_negated diff --git a/test/dummy/app/models/size/matcher.rb b/test/dummy/app/models/size/matcher.rb index 376490e..34bc0c5 100644 --- a/test/dummy/app/models/size/matcher.rb +++ b/test/dummy/app/models/size/matcher.rb @@ -11,6 +11,8 @@ # class Size::Matcher < ApplicationRecord + include Validatable + has_one_attached :less_than has_one_attached :less_than_or_equal_to has_one_attached :greater_than @@ -47,6 +49,10 @@ class Size::Matcher < ApplicationRecord has_one_attached :as_instance validates :as_instance, size: { less_than_or_equal_to: 5.megabytes } + has_one_attached :validatable_different_error_messages + validates :validatable_different_error_messages, size: { less_than: 20.megabytes, message: 'Custom message 1' }, if: :title_is_quo_vadis? + validates :validatable_different_error_messages, size: { less_than: 10.megabytes, message: 'Custom message 2' }, if: :title_is_american_psycho? + has_one_attached :failure_message validates :failure_message, size: { less_than_or_equal_to: 5.megabytes } has_one_attached :failure_message_when_negated diff --git a/test/matchers/aspect_ratio_validator_matcher_test.rb b/test/matchers/aspect_ratio_validator_matcher_test.rb index 9128b67..ad2beaf 100644 --- a/test/matchers/aspect_ratio_validator_matcher_test.rb +++ b/test/matchers/aspect_ratio_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/checks_if_is_valid' require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' @@ -11,8 +12,9 @@ describe ActiveStorageValidations::Matchers::AspectRatioValidatorMatcher do include MatcherHelpers - include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute + include ChecksIfIsValid + include HasValidRspecMessageMethods include WorksWithBothInstanceAndClass let(:matcher) { ActiveStorageValidations::Matchers::AspectRatioValidatorMatcher.new(model_attribute) } diff --git a/test/matchers/attached_validator_matcher_test.rb b/test/matchers/attached_validator_matcher_test.rb index 39e1b71..acc6acb 100644 --- a/test/matchers/attached_validator_matcher_test.rb +++ b/test/matchers/attached_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/checks_if_is_valid' require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_both_instance_and_class' require 'matchers/shared_examples/works_with_context' @@ -10,8 +11,9 @@ describe ActiveStorageValidations::Matchers::AttachedValidatorMatcher do include MatcherHelpers - include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute + include ChecksIfIsValid + include HasValidRspecMessageMethods include WorksWithBothInstanceAndClass let(:matcher) { ActiveStorageValidations::Matchers::AttachedValidatorMatcher.new(model_attribute) } diff --git a/test/matchers/content_type_validator_matcher_test.rb b/test/matchers/content_type_validator_matcher_test.rb index 1c4e844..0d67498 100644 --- a/test/matchers/content_type_validator_matcher_test.rb +++ b/test/matchers/content_type_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/checks_if_is_valid' require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' @@ -11,8 +12,9 @@ describe ActiveStorageValidations::Matchers::ContentTypeValidatorMatcher do include MatcherHelpers - include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute + include ChecksIfIsValid + include HasValidRspecMessageMethods include WorksWithBothInstanceAndClass let(:matcher) { ActiveStorageValidations::Matchers::ContentTypeValidatorMatcher.new(model_attribute) } diff --git a/test/matchers/dimension_validator_matcher_test.rb b/test/matchers/dimension_validator_matcher_test.rb index f2d28e5..9712a3a 100644 --- a/test/matchers/dimension_validator_matcher_test.rb +++ b/test/matchers/dimension_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/checks_if_is_valid' require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' @@ -141,8 +142,9 @@ module OnlyMatchWhenExactValues describe ActiveStorageValidations::Matchers::DimensionValidatorMatcher do include MatcherHelpers - include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute + include ChecksIfIsValid + include HasValidRspecMessageMethods include WorksWithBothInstanceAndClass let(:matcher) { ActiveStorageValidations::Matchers::DimensionValidatorMatcher.new(model_attribute) } diff --git a/test/matchers/shared_examples/checks_if_is_valid.rb b/test/matchers/shared_examples/checks_if_is_valid.rb new file mode 100644 index 0000000..6143e7a --- /dev/null +++ b/test/matchers/shared_examples/checks_if_is_valid.rb @@ -0,0 +1,28 @@ +module ChecksIfIsValid + extend ActiveSupport::Concern + + included do + describe 'Edge cases' do + describe 'when the validator is used several times on the same attributes' do + describe 'and is provided with different error messages' do + before do + case validator_sym + when :aspect_ratio then matcher.allowing(:square) + when :attached then matcher + when :content_type then matcher.rejecting('image/jpg') + when :dimension then matcher.width(150) + when :size then matcher.less_than(10.megabytes) + end + end + + subject { matcher } + + let(:model_attribute) { :validatable_different_error_messages } + let(:instance) { klass.new(title: "American Psycho") } + + it { is_expected_to_match_for(instance) } + end + end + end + end +end diff --git a/test/matchers/size_validator_matcher_test.rb b/test/matchers/size_validator_matcher_test.rb index 8d694d9..6126ddc 100644 --- a/test/matchers/size_validator_matcher_test.rb +++ b/test/matchers/size_validator_matcher_test.rb @@ -2,6 +2,7 @@ require 'test_helper' require 'matchers/shared_examples/checks_if_is_a_valid_active_storage_attribute' +require 'matchers/shared_examples/checks_if_is_valid' require 'matchers/shared_examples/has_valid_rspec_message_methods' require 'matchers/shared_examples/works_with_allow_blank' require 'matchers/shared_examples/works_with_both_instance_and_class' @@ -61,8 +62,9 @@ module OnlyMatchWhenExactValue describe ActiveStorageValidations::Matchers::SizeValidatorMatcher do include MatcherHelpers - include HasValidRspecMessageMethods include ChecksIfIsAValidActiveStorageAttribute + include ChecksIfIsValid + include HasValidRspecMessageMethods include WorksWithBothInstanceAndClass let(:matcher) { ActiveStorageValidations::Matchers::SizeValidatorMatcher.new(model_attribute) }