From 628774972f4221d5dac8f7b5f260dad139c18b35 Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Tue, 31 Oct 2023 22:55:20 +0100 Subject: [PATCH 1/7] Update Gemfile.lock --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index df66c8fa..041f3a88 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_storage_validations (1.1.0) + active_storage_validations (1.1.1) activejob (>= 5.2.0) activemodel (>= 5.2.0) activestorage (>= 5.2.0) From dcfda409e73dd29d40c470c717b06835303405a7 Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Tue, 31 Oct 2023 22:56:31 +0100 Subject: [PATCH 2/7] Fix: Make sure to filter out extra keys from options and pick the correct value --- lib/active_storage_validations/size_validator.rb | 3 ++- test/dummy/app/models/size/portfolio.rb | 2 ++ test/validators/size_validator_test.rb | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/active_storage_validations/size_validator.rb b/lib/active_storage_validations/size_validator.rb index 67b04350..eb66c5b7 100644 --- a/lib/active_storage_validations/size_validator.rb +++ b/lib/active_storage_validations/size_validator.rb @@ -31,7 +31,8 @@ def validate_each(record, attribute, _value) errors_options[:file_size] = number_to_human_size(file.blob.byte_size) errors_options[:min_size] = number_to_human_size(min_size(flat_options)) errors_options[:max_size] = number_to_human_size(max_size(flat_options)) - error_type = "file_size_not_#{flat_options.keys.first}".to_sym + keys = AVAILABLE_CHECKS & options.keys + error_type = "file_size_not_#{keys.first}".to_sym add_error(record, attribute, error_type, **errors_options) break diff --git a/test/dummy/app/models/size/portfolio.rb b/test/dummy/app/models/size/portfolio.rb index 3f26b8ea..6c93cbf8 100644 --- a/test/dummy/app/models/size/portfolio.rb +++ b/test/dummy/app/models/size/portfolio.rb @@ -17,6 +17,7 @@ class Size::Portfolio < ApplicationRecord has_one_attached :size_greater_than_or_equal_to has_one_attached :size_between has_one_attached :size_with_message + has_one_attached :size_with_context has_one_attached :proc_size_less_than has_one_attached :proc_size_less_than_or_equal_to @@ -33,6 +34,7 @@ class Size::Portfolio < ApplicationRecord validates :size_greater_than_or_equal_to, size: { greater_than_or_equal_to: 7.kilobytes } validates :size_between, size: { between: 2.kilobytes..7.kilobytes } validates :size_with_message, size: { between: 2.kilobytes..7.kilobytes, message: 'is not in required file size range' } + validates :size_with_context, size: { less_than: 2.kilobytes }, on: :custom_context validates :proc_size_less_than, size: { less_than: -> (record) { 2.kilobytes } } validates :proc_size_less_than_or_equal_to, size: { less_than_or_equal_to: -> (record) { 2.kilobytes } } diff --git a/test/validators/size_validator_test.rb b/test/validators/size_validator_test.rb index 4fd93e0b..8c30b358 100644 --- a/test/validators/size_validator_test.rb +++ b/test/validators/size_validator_test.rb @@ -239,6 +239,22 @@ def error_message end end + class WithContext < ActiveStorageValidations::SizeValidator::Test + # validates :size_with_context, size: { less_than: 2.kilobytes }, on: :custom_context + + test 'generates correct error message' do + pt = Size::Portfolio.new(title: 'Matisse') + pt.size_with_context.attach(file_10ko) + + refute pt.invalid? + pt.valid?(:custom_context) + + assert_equal( + ['Size with context file size must be less than 2 KB (current size is 10 KB)'], + pt.errors.full_messages + ) + end + end end def file_1ko From 08538234446a72b70bfa8f29d77c12936bb4c60c Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Tue, 31 Oct 2023 23:27:28 +0100 Subject: [PATCH 3/7] Feat: Extend matcher to give a possibility to define validation context --- .../matchers/size_validator_matcher.rb | 10 +++++++++- test/matchers/size_validator_matcher_test.rb | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/active_storage_validations/matchers/size_validator_matcher.rb b/lib/active_storage_validations/matchers/size_validator_matcher.rb index b234f978..90ff5f66 100644 --- a/lib/active_storage_validations/matchers/size_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/size_validator_matcher.rb @@ -49,6 +49,10 @@ def with_message(message) self end + def on(context) + @context = context + end + def matches?(subject) @subject = subject.is_a?(Class) ? subject.new : subject responds_to_methods && not_lower_than_min? && higher_than_min? && lower_than_max? && not_higher_than_max? @@ -86,11 +90,15 @@ def not_higher_than_max? @max.nil? || @max == Float::INFINITY || !passes_validation_with_size(@max + 1) end + def validate + @subject.validate(@context) + end + def passes_validation_with_size(new_size) io = Tempfile.new('Hello world!') Matchers.stub_method(io, :size, new_size) do @subject.public_send(@attribute_name).attach(io: io, filename: 'test.png', content_type: 'image/pg') - @subject.validate + validate exclude_error_message = @custom_message || "file_size_not_" @subject.errors.details[@attribute_name].none? do |error| error[:error].to_s.include?(exclude_error_message) diff --git a/test/matchers/size_validator_matcher_test.rb b/test/matchers/size_validator_matcher_test.rb index 1a3b6f80..075addaa 100644 --- a/test/matchers/size_validator_matcher_test.rb +++ b/test/matchers/size_validator_matcher_test.rb @@ -153,6 +153,14 @@ class UnknownAttachedAttribute < ActiveStorageValidations::Matchers::SizeValidat end end + class WithContextMatcher < ActiveStorageValidations::Matchers::SizeValidatorMatcher::Test + test 'matches when provided with the validation context' do + matcher = ActiveStorageValidations::Matchers::SizeValidatorMatcher.new(:size_with_context) + matcher.less_than 2.kilobytes + matcher.on(:custom_context) + assert matcher.matches?(Size::Portfolio) + end + end # Other tests test 'matches when provided with an instance' do From 733742fbc06ba0b4d7ee8feac08af051ff069121 Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Fri, 3 Nov 2023 18:16:53 +0100 Subject: [PATCH 4/7] chore(cr): Initialize @context with nil --- .../matchers/size_validator_matcher.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/active_storage_validations/matchers/size_validator_matcher.rb b/lib/active_storage_validations/matchers/size_validator_matcher.rb index 90ff5f66..6633a471 100644 --- a/lib/active_storage_validations/matchers/size_validator_matcher.rb +++ b/lib/active_storage_validations/matchers/size_validator_matcher.rb @@ -13,6 +13,7 @@ def initialize(attribute_name) @attribute_name = attribute_name @min = @max = nil @custom_message = nil + @context = nil end def description From 5ad49da491b0e1a02373c66929a2cdbd82c56e4a Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Fri, 3 Nov 2023 18:17:44 +0100 Subject: [PATCH 5/7] chore(cr): use existing flat_options variables instead --- lib/active_storage_validations/size_validator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/active_storage_validations/size_validator.rb b/lib/active_storage_validations/size_validator.rb index eb66c5b7..49afa38d 100644 --- a/lib/active_storage_validations/size_validator.rb +++ b/lib/active_storage_validations/size_validator.rb @@ -31,7 +31,7 @@ def validate_each(record, attribute, _value) errors_options[:file_size] = number_to_human_size(file.blob.byte_size) errors_options[:min_size] = number_to_human_size(min_size(flat_options)) errors_options[:max_size] = number_to_human_size(max_size(flat_options)) - keys = AVAILABLE_CHECKS & options.keys + keys = AVAILABLE_CHECKS & flat_options.keys error_type = "file_size_not_#{keys.first}".to_sym add_error(record, attribute, error_type, **errors_options) From 90b24e35dbffb0d97d3290ad66680c2bccd154ca Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Fri, 3 Nov 2023 18:25:07 +0100 Subject: [PATCH 6/7] chore(cr): Add tests for attachment validation with if condition --- test/dummy/app/models/size/portfolio.rb | 2 ++ test/validators/size_validator_test.rb | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/test/dummy/app/models/size/portfolio.rb b/test/dummy/app/models/size/portfolio.rb index 6c93cbf8..22baf32c 100644 --- a/test/dummy/app/models/size/portfolio.rb +++ b/test/dummy/app/models/size/portfolio.rb @@ -18,6 +18,7 @@ class Size::Portfolio < ApplicationRecord has_one_attached :size_between has_one_attached :size_with_message has_one_attached :size_with_context + has_one_attached :size_with_if has_one_attached :proc_size_less_than has_one_attached :proc_size_less_than_or_equal_to @@ -35,6 +36,7 @@ class Size::Portfolio < ApplicationRecord validates :size_between, size: { between: 2.kilobytes..7.kilobytes } validates :size_with_message, size: { between: 2.kilobytes..7.kilobytes, message: 'is not in required file size range' } validates :size_with_context, size: { less_than: 2.kilobytes }, on: :custom_context + validates :size_with_if, size: { less_than: 2.kilobytes }, if: -> { title == 'very_nice_title' } validates :proc_size_less_than, size: { less_than: -> (record) { 2.kilobytes } } validates :proc_size_less_than_or_equal_to, size: { less_than_or_equal_to: -> (record) { 2.kilobytes } } diff --git a/test/validators/size_validator_test.rb b/test/validators/size_validator_test.rb index 8c30b358..d53280f5 100644 --- a/test/validators/size_validator_test.rb +++ b/test/validators/size_validator_test.rb @@ -255,6 +255,25 @@ class WithContext < ActiveStorageValidations::SizeValidator::Test ) end end + + class WithIf < ActiveStorageValidations::SizeValidator::Test + # validates :size_with_if, size: { less_than: 2.kilobytes }, if: -> { title == 'very_nice_title' } + + test 'generates correct error message' do + pt = Size::Portfolio.new(title: 'Matisse') + pt.size_with_if.attach(file_10ko) + + refute pt.invalid? + + pt.title = 'very_nice_title' + refute pt.valid? + + assert_equal( + ['Size with if file size must be less than 2 KB (current size is 10 KB)'], + pt.errors.full_messages + ) + end + end end def file_1ko From 3034195a41c026132f2d86fb59e7dbb87ef91b7b Mon Sep 17 00:00:00 2001 From: jozzi05 Date: Fri, 3 Nov 2023 18:25:24 +0100 Subject: [PATCH 7/7] chore: Add extra check --- test/validators/size_validator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/validators/size_validator_test.rb b/test/validators/size_validator_test.rb index d53280f5..9da7e117 100644 --- a/test/validators/size_validator_test.rb +++ b/test/validators/size_validator_test.rb @@ -247,7 +247,7 @@ class WithContext < ActiveStorageValidations::SizeValidator::Test pt.size_with_context.attach(file_10ko) refute pt.invalid? - pt.valid?(:custom_context) + refute pt.valid?(:custom_context) assert_equal( ['Size with context file size must be less than 2 KB (current size is 10 KB)'],