Skip to content

Commit

Permalink
[Matcher] Update contextable to match validatable changes (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mth0158 committed Jan 3, 2024
1 parent b9ac7bd commit 2c81b27
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 39 deletions.
28 changes: 20 additions & 8 deletions lib/active_storage_validations/matchers/concerns/contextable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,31 @@ def on(context)
private

def is_context_valid?
return true if !@context && !(attribute_validator && attribute_validator.options[:on])
return true if !@context && attribute_validators.none? { |validator| validator.options[:on] }

raise ArgumentError, "This validator matcher needs the #on option to work since its validator has one" if !@context
raise ArgumentError, "This validator matcher needs the #on option to work since its validator has one" if !@context && attribute_validators.all? { |validator| validator.options[:on] }
raise ArgumentError, "This validator matcher option only allows a symbol or an array" if !(@context.is_a?(Symbol) || @context.is_a?(Array))

if @context.is_a?(Array) && attribute_validator.options[:on].is_a?(Array)
@context.to_set == attribute_validator.options[:on].to_set
elsif @context.is_a?(Symbol) && attribute_validator.options[:on].is_a?(Symbol)
@context == attribute_validator.options[:on]
else
false
if @context.is_a?(Array)
(validator_contexts & @context.map(&:to_s)) == validator_contexts || raise_context_not_listed_error
elsif @context.is_a?(Symbol)
validator_contexts.include?(@context.to_s) || raise_context_not_listed_error
end
end

def validator_contexts
attribute_validators.map do |validator|
case validator.options[:on]
when Array then validator.options[:on].map { |context| context.to_s }
when NilClass then nil
else validator.options[:on].to_s
end
end.flatten.compact
end

def raise_context_not_listed_error
raise ArgumentError, "One of the provided contexts to the #on method is not found in any of the listed contexts for this attribute"
end
end
end
end
12 changes: 7 additions & 5 deletions lib/active_storage_validations/matchers/concerns/validatable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ def attribute_validator
end
end

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
def attribute_validators
@subject.class.validators_on(@attribute_name).select do |validator|
validator.class == validator_class
end
end

def errors_from_custom_messages
attribute_validators.map { |validator| validator.options[:message] }
end
end
end
end
3 changes: 3 additions & 0 deletions test/dummy/app/models/aspect_ratio/matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class AspectRatio::Matcher < ApplicationRecord
validates :with_context_symbol, aspect_ratio: :square, on: :update
has_one_attached :with_context_array
validates :with_context_array, aspect_ratio: :square, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, aspect_ratio: :square, on: :update
validates :with_several_validators_and_contexts, aspect_ratio: :square, on: :custom

has_one_attached :as_instance
validates :as_instance, aspect_ratio: :square
Expand Down
3 changes: 3 additions & 0 deletions test/dummy/app/models/attached/matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class Attached::Matcher < ApplicationRecord
validates :with_context_symbol, attached: true, on: :update
has_one_attached :with_context_array
validates :with_context_array, attached: true, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, attached: true, on: :update
validates :with_several_validators_and_contexts, attached: true, on: :custom

has_one_attached :as_instance
validates :as_instance, attached: true
Expand Down
3 changes: 3 additions & 0 deletions test/dummy/app/models/content_type/matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class ContentType::Matcher < ApplicationRecord
validates :with_context_symbol, content_type: :png, on: :update
has_one_attached :with_context_array
validates :with_context_array, content_type: :png, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, content_type: :png, on: :update
validates :with_several_validators_and_contexts, content_type: :png, on: :custom

has_one_attached :as_instance
validates :as_instance, content_type: :png
Expand Down
3 changes: 3 additions & 0 deletions test/dummy/app/models/dimension/matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class Dimension::Matcher < ApplicationRecord
validates :with_context_symbol, dimension: { width: 150, height: 150 }, on: :update
has_one_attached :with_context_array
validates :with_context_array, dimension: { width: 150, height: 150 }, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, dimension: { width: 150, height: 150 }, on: :update
validates :with_several_validators_and_contexts, dimension: { width: 150, height: 150 }, on: :custom

has_one_attached :as_instance
validates :as_instance, dimension: { width: 150, height: 150 }
Expand Down
3 changes: 3 additions & 0 deletions test/dummy/app/models/size/matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class Size::Matcher < ApplicationRecord
validates :with_context_symbol, size: { less_than_or_equal_to: 5.megabytes }, on: :update
has_one_attached :with_context_array
validates :with_context_array, size: { less_than_or_equal_to: 5.megabytes }, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, size: { less_than_or_equal_to: 5.megabytes }, on: :update
validates :with_several_validators_and_contexts, size: { less_than_or_equal_to: 5.megabytes }, on: :custom

has_one_attached :as_instance
validates :as_instance, size: { less_than_or_equal_to: 5.megabytes }
Expand Down
80 changes: 56 additions & 24 deletions test/matchers/shared_examples/works_with_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,80 @@ module WorksWithContext
extend ActiveSupport::Concern

included do
describe 'when provided with the model validation context' do
describe 'which is an symbol' do
subject { matcher.on(:update) }
describe 'when the model attribute has a context' do
describe 'and the matcher is provided with the model attribute validator context' do
describe 'which is an symbol' do
subject { matcher.on(:update) }

let(:model_attribute) { :with_context_symbol }
let(:model_attribute) { :with_context_symbol }

it { is_expected_to_match_for(klass) }
end
it { is_expected_to_match_for(klass) }
end

describe 'which is an array' do
subject { matcher.on(%i[update custom]) }
describe 'which is an array' do
subject { matcher.on(%i[update custom]) }

let(:model_attribute) { :with_context_array }
let(:model_attribute) { :with_context_array }

it { is_expected_to_match_for(klass) }
it { is_expected_to_match_for(klass) }
end
end
end

describe 'when provided with a different context than the model validation context' do
describe 'which is an symbol' do
subject { matcher.on(:custom2) }
describe 'and the matcher is provided with a different context than the model attribute validator context' do
describe 'which is an symbol' do
subject { matcher.on(:custom2) }

let(:model_attribute) { :with_context_symbol }
let(:model_attribute) { :with_context_symbol }

it { is_expected_not_to_match_for(klass) }
it { is_expected_to_raise_error(ArgumentError, 'One of the provided contexts to the #on method is not found in any of the listed contexts for this attribute') }
end

describe 'which is an array' do
subject { matcher.on(%i[update custom2]) }

let(:model_attribute) { :with_context_array }

it { is_expected_to_raise_error(ArgumentError, 'One of the provided contexts to the #on method is not found in any of the listed contexts for this attribute') }
end
end

describe 'which is an array' do
subject { matcher.on(%i[update custom2]) }
describe 'but the matcher is not provided with the #on method' do
subject { matcher }

let(:model_attribute) { :with_context_array }
let(:model_attribute) { :with_context_symbol }

it { is_expected_not_to_match_for(klass) }
it { is_expected_to_raise_error(ArgumentError, 'This validator matcher needs the #on option to work since its validator has one') }
end
end

describe 'when not provided with the #on matcher method' do
subject { matcher }
describe 'when the model attribute uses an active_storage_validation validator several times' do
describe 'with several contexts' do
describe 'and the matcher is provided with' do
describe 'one of the model attribute validators contexts' do
subject { matcher.on(:custom) }

let(:model_attribute) { :with_context_symbol }
let(:model_attribute) { :with_several_validators_and_contexts }

it { is_expected_to_raise_error(ArgumentError, 'This validator matcher needs the #on option to work since its validator has one') }
it { is_expected_to_match_for(klass) }
end

describe 'all of the model attribute validators contexts' do
subject { matcher.on(%i[update custom]) }

let(:model_attribute) { :with_several_validators_and_contexts }

it { is_expected_to_match_for(klass) }
end

describe 'one context that is not present in the model attribute validators contexts' do
subject { matcher.on(:not_present) }

let(:model_attribute) { :with_several_validators_and_contexts }

it { is_expected_to_raise_error(ArgumentError, 'One of the provided contexts to the #on method is not found in any of the listed contexts for this attribute') }
end
end
end
end
end
end
5 changes: 4 additions & 1 deletion test/matchers/support/matcher_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ def is_expected_not_to_match_for(klass)
end

def is_expected_to_raise_error(error_class, message)
begin subject.matches?(klass)
begin
subject.matches?(klass)
rescue => e
assert_equal(e.class, error_class)
assert(e.message.include?(message))
else
raise StandardError, "It should raise an error but it does not raise any"
end
end

Expand Down
5 changes: 4 additions & 1 deletion test/validators/support/validator_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ def is_expected_to_have_error_message(message_key, **kwargs)
end

def is_expected_to_raise_error(error_class, message)
begin subject.valid?
begin
subject.valid?
rescue => e
assert_equal(e.class, error_class)
assert(e.message.include?(message))
else
raise StandardError, "It should raise an error but it does not raise any"
end
end

Expand Down

0 comments on commit 2c81b27

Please sign in to comment.