active_storage_validations 1.1.3 → 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +81 -55
  3. data/lib/active_storage_validations/aspect_ratio_validator.rb +47 -22
  4. data/lib/active_storage_validations/attached_validator.rb +12 -3
  5. data/lib/active_storage_validations/concerns/errorable.rb +38 -0
  6. data/lib/active_storage_validations/concerns/symbolizable.rb +8 -6
  7. data/lib/active_storage_validations/content_type_validator.rb +41 -6
  8. data/lib/active_storage_validations/dimension_validator.rb +15 -15
  9. data/lib/active_storage_validations/limit_validator.rb +44 -7
  10. data/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +128 -0
  11. data/lib/active_storage_validations/matchers/attached_validator_matcher.rb +20 -23
  12. data/lib/active_storage_validations/matchers/concerns/active_storageable.rb +17 -0
  13. data/lib/active_storage_validations/matchers/concerns/allow_blankable.rb +26 -0
  14. data/lib/active_storage_validations/matchers/concerns/contextable.rb +35 -0
  15. data/lib/active_storage_validations/matchers/concerns/messageable.rb +26 -0
  16. data/lib/active_storage_validations/matchers/concerns/rspecable.rb +25 -0
  17. data/lib/active_storage_validations/matchers/concerns/validatable.rb +5 -10
  18. data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +39 -25
  19. data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +61 -44
  20. data/lib/active_storage_validations/matchers/size_validator_matcher.rb +41 -24
  21. data/lib/active_storage_validations/matchers.rb +1 -0
  22. data/lib/active_storage_validations/metadata.rb +42 -28
  23. data/lib/active_storage_validations/processable_image_validator.rb +14 -5
  24. data/lib/active_storage_validations/size_validator.rb +7 -6
  25. data/lib/active_storage_validations/version.rb +1 -1
  26. data/lib/active_storage_validations.rb +1 -1
  27. metadata +9 -3
  28. data/lib/active_storage_validations/error_handler.rb +0 -21
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'concerns/active_storageable.rb'
4
+ require_relative 'concerns/allow_blankable.rb'
5
+ require_relative 'concerns/contextable.rb'
6
+ require_relative 'concerns/messageable.rb'
7
+ require_relative 'concerns/rspecable.rb'
3
8
  require_relative 'concerns/validatable.rb'
4
9
 
5
10
  module ActiveStorageValidations
@@ -9,16 +14,35 @@ module ActiveStorageValidations
9
14
  end
10
15
 
11
16
  class DimensionValidatorMatcher
17
+ include ActiveStorageable
18
+ include AllowBlankable
19
+ include Contextable
20
+ include Messageable
21
+ include Rspecable
12
22
  include Validatable
13
23
 
14
24
  def initialize(attribute_name)
25
+ initialize_allow_blankable
26
+ initialize_contextable
27
+ initialize_messageable
28
+ initialize_rspecable
15
29
  @attribute_name = attribute_name
16
30
  @width_min = @width_max = @height_min = @height_max = nil
17
- @custom_message = nil
18
31
  end
19
32
 
20
33
  def description
21
- "validate image dimensions of #{@attribute_name}"
34
+ "validate the image dimensions of :#{@attribute_name}"
35
+ end
36
+
37
+ def failure_message
38
+ message = ["is expected to validate dimensions of :#{@attribute_name}"]
39
+ build_failure_message(message)
40
+ message.join("\n")
41
+ end
42
+
43
+ def width(width)
44
+ @width_min = @width_max = width
45
+ self
22
46
  end
23
47
 
24
48
  def width_min(width)
@@ -31,13 +55,13 @@ module ActiveStorageValidations
31
55
  self
32
56
  end
33
57
 
34
- def with_message(message)
35
- @custom_message = message
58
+ def width_between(range)
59
+ @width_min, @width_max = range.first, range.last
36
60
  self
37
61
  end
38
62
 
39
- def width(width)
40
- @width_min = @width_max = width
63
+ def height(height)
64
+ @height_min = @height_max = height
41
65
  self
42
66
  end
43
67
 
@@ -51,25 +75,18 @@ module ActiveStorageValidations
51
75
  self
52
76
  end
53
77
 
54
- def width_between(range)
55
- @width_min, @width_max = range.first, range.last
56
- self
57
- end
58
-
59
78
  def height_between(range)
60
79
  @height_min, @height_max = range.first, range.last
61
80
  self
62
81
  end
63
82
 
64
- def height(height)
65
- @height_min = @height_max = height
66
- self
67
- end
68
-
69
83
  def matches?(subject)
70
84
  @subject = subject.is_a?(Class) ? subject.new : subject
71
85
 
72
- responds_to_methods &&
86
+ is_a_valid_active_storage_attribute? &&
87
+ is_context_valid? &&
88
+ is_allowing_blank? &&
89
+ is_custom_message_valid? &&
73
90
  width_not_smaller_than_min? &&
74
91
  width_larger_than_min? &&
75
92
  width_smaller_than_max? &&
@@ -79,24 +96,19 @@ module ActiveStorageValidations
79
96
  height_larger_than_min? &&
80
97
  height_smaller_than_max? &&
81
98
  height_not_larger_than_max? &&
82
- height_equals? &&
83
- validate_custom_message?
84
- end
85
-
86
- def failure_message
87
- <<~MESSAGE
88
- is expected to validate dimensions of #{@attribute_name}
89
- width between #{@width_min} and #{@width_max}
90
- height between #{@height_min} and #{@height_max}
91
- MESSAGE
99
+ height_equals?
92
100
  end
93
101
 
94
102
  protected
95
103
 
96
- def responds_to_methods
97
- @subject.respond_to?(@attribute_name) &&
98
- @subject.public_send(@attribute_name).respond_to?(:attach) &&
99
- @subject.public_send(@attribute_name).respond_to?(:detach)
104
+ def build_failure_message(message)
105
+ return unless @failure_message_artefacts.present?
106
+
107
+ message << " but there seem to have issues with the matcher methods you used, since:"
108
+ @failure_message_artefacts.each do |error_case|
109
+ message << " validation failed when provided with a #{error_case[:width]}x#{error_case[:height]}px test image"
110
+ end
111
+ message << " whereas it should have passed"
100
112
  end
101
113
 
102
114
  def valid_width
@@ -108,53 +120,58 @@ module ActiveStorageValidations
108
120
  end
109
121
 
110
122
  def width_not_smaller_than_min?
111
- @width_min.nil? || !passes_validation_with_dimensions(@width_min - 1, valid_height, 'width')
123
+ @width_min.nil? || !passes_validation_with_dimensions(@width_min - 1, valid_height)
112
124
  end
113
125
 
114
126
  def width_larger_than_min?
115
- @width_min.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_min + 1, valid_height, 'width')
127
+ @width_min.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_min + 1, valid_height)
116
128
  end
117
129
 
118
130
  def width_smaller_than_max?
119
- @width_max.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_max - 1, valid_height, 'width')
131
+ @width_max.nil? || @width_min == @width_max || passes_validation_with_dimensions(@width_max - 1, valid_height)
120
132
  end
121
133
 
122
134
  def width_not_larger_than_max?
123
- @width_max.nil? || !passes_validation_with_dimensions(@width_max + 1, valid_height, 'width')
135
+ @width_max.nil? || !passes_validation_with_dimensions(@width_max + 1, valid_height)
124
136
  end
125
137
 
126
138
  def width_equals?
127
- @width_min.nil? || @width_min != @width_max || passes_validation_with_dimensions(@width_min, valid_height, 'width')
139
+ @width_min.nil? || @width_min != @width_max || passes_validation_with_dimensions(@width_min, valid_height)
128
140
  end
129
141
 
130
142
  def height_not_smaller_than_min?
131
- @height_min.nil? || !passes_validation_with_dimensions(valid_width, @height_min - 1, 'height')
143
+ @height_min.nil? || !passes_validation_with_dimensions(valid_width, @height_min - 1)
132
144
  end
133
145
 
134
146
  def height_larger_than_min?
135
- @height_min.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_min + 1, 'height')
147
+ @height_min.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_min + 1)
136
148
  end
137
149
 
138
150
  def height_smaller_than_max?
139
- @height_max.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_max - 1, 'height')
151
+ @height_max.nil? || @height_min == @height_max || passes_validation_with_dimensions(valid_width, @height_max - 1)
140
152
  end
141
153
 
142
154
  def height_not_larger_than_max?
143
- @height_max.nil? || !passes_validation_with_dimensions(valid_width, @height_max + 1, 'height')
155
+ @height_max.nil? || !passes_validation_with_dimensions(valid_width, @height_max + 1)
144
156
  end
145
157
 
146
158
  def height_equals?
147
- @height_min.nil? || @height_min != @height_max || passes_validation_with_dimensions(valid_width, @height_min, 'height')
159
+ @height_min.nil? || @height_min != @height_max || passes_validation_with_dimensions(valid_width, @height_min)
148
160
  end
149
161
 
150
- def passes_validation_with_dimensions(width, height, check)
162
+ def passes_validation_with_dimensions(width, height)
151
163
  mock_dimensions_for(attach_file, width, height) do
152
164
  validate
153
- is_valid?
165
+ is_valid? || add_failure_message_artefact(width, height)
154
166
  end
155
167
  end
156
168
 
157
- def validate_custom_message?
169
+ def add_failure_message_artefact(width, height)
170
+ @failure_message_artefacts << { width: width, height: height }
171
+ false
172
+ end
173
+
174
+ def is_custom_message_valid?
158
175
  return true unless @custom_message
159
176
 
160
177
  mock_dimensions_for(attach_file, -1, -1) do
@@ -3,6 +3,11 @@
3
3
  # Big thank you to the paperclip validation matchers:
4
4
  # https://github.com/thoughtbot/paperclip/blob/v6.1.0/lib/paperclip/matchers/validate_attachment_size_matcher.rb
5
5
 
6
+ require_relative 'concerns/active_storageable.rb'
7
+ require_relative 'concerns/allow_blankable.rb'
8
+ require_relative 'concerns/contextable.rb'
9
+ require_relative 'concerns/messageable.rb'
10
+ require_relative 'concerns/rspecable.rb'
6
11
  require_relative 'concerns/validatable.rb'
7
12
 
8
13
  module ActiveStorageValidations
@@ -12,16 +17,30 @@ module ActiveStorageValidations
12
17
  end
13
18
 
14
19
  class SizeValidatorMatcher
20
+ include ActiveStorageable
21
+ include AllowBlankable
22
+ include Contextable
23
+ include Messageable
24
+ include Rspecable
15
25
  include Validatable
16
26
 
17
27
  def initialize(attribute_name)
28
+ initialize_allow_blankable
29
+ initialize_contextable
30
+ initialize_messageable
31
+ initialize_rspecable
18
32
  @attribute_name = attribute_name
19
33
  @min = @max = nil
20
- @custom_message = nil
21
34
  end
22
35
 
23
36
  def description
24
- "validate file size of #{@attribute_name}"
37
+ "validate file size of :#{@attribute_name}"
38
+ end
39
+
40
+ def failure_message
41
+ message = ["is expected to validate file size of :#{@attribute_name}"]
42
+ build_failure_message(message)
43
+ message.join("\n")
25
44
  end
26
45
 
27
46
  def less_than(size)
@@ -49,36 +68,29 @@ module ActiveStorageValidations
49
68
  self
50
69
  end
51
70
 
52
- def with_message(message)
53
- @custom_message = message
54
- self
55
- end
56
-
57
71
  def matches?(subject)
58
72
  @subject = subject.is_a?(Class) ? subject.new : subject
59
73
 
60
- responds_to_methods &&
74
+ is_a_valid_active_storage_attribute? &&
75
+ is_context_valid? &&
76
+ is_allowing_blank? &&
77
+ is_custom_message_valid? &&
61
78
  not_lower_than_min? &&
62
79
  higher_than_min? &&
63
80
  lower_than_max? &&
64
- not_higher_than_max? &&
65
- validate_custom_message?
66
- end
67
-
68
- def failure_message
69
- "is expected to validate file size of #{@attribute_name} to be between #{@min} and #{@max} bytes"
70
- end
71
-
72
- def failure_message_when_negated
73
- "is expected to not validate file size of #{@attribute_name} to be between #{@min} and #{@max} bytes"
81
+ not_higher_than_max?
74
82
  end
75
83
 
76
84
  protected
77
85
 
78
- def responds_to_methods
79
- @subject.respond_to?(@attribute_name) &&
80
- @subject.public_send(@attribute_name).respond_to?(:attach) &&
81
- @subject.public_send(@attribute_name).respond_to?(:detach)
86
+ def build_failure_message(message)
87
+ return unless @failure_message_artefacts.present?
88
+
89
+ message << " but there seem to have issues with the matcher methods you used, since:"
90
+ @failure_message_artefacts.each do |error_case|
91
+ message << " validation failed when provided with a #{error_case[:size]} bytes test file"
92
+ end
93
+ message << " whereas it should have passed"
82
94
  end
83
95
 
84
96
  def not_lower_than_min?
@@ -101,11 +113,16 @@ module ActiveStorageValidations
101
113
  mock_size_for(io, size) do
102
114
  attach_file
103
115
  validate
104
- is_valid?
116
+ is_valid? || add_failure_message_artefact(size)
105
117
  end
106
118
  end
107
119
 
108
- def validate_custom_message?
120
+ def add_failure_message_artefact(size)
121
+ @failure_message_artefacts << { size: size }
122
+ false
123
+ end
124
+
125
+ def is_custom_message_valid?
109
126
  return true unless @custom_message
110
127
 
111
128
  mock_size_for(io, -1.kilobytes) do
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_storage_validations/matchers/aspect_ratio_validator_matcher'
3
4
  require 'active_storage_validations/matchers/attached_validator_matcher'
4
5
  require 'active_storage_validations/matchers/content_type_validator_matcher'
5
6
  require 'active_storage_validations/matchers/dimension_validator_matcher'
@@ -4,29 +4,18 @@ module ActiveStorageValidations
4
4
 
5
5
  attr_reader :file
6
6
 
7
+ DEFAULT_IMAGE_PROCESSOR = :mini_magick.freeze
8
+
7
9
  def initialize(file)
8
10
  require_image_processor
9
11
  @file = file
10
12
  end
11
13
 
12
- def image_processor
13
- Rails.application.config.active_storage.variant_processor
14
- end
15
-
16
- def exception_class
17
- if image_processor == :vips && defined?(Vips)
18
- Vips::Error
19
- elsif defined?(MiniMagick)
20
- MiniMagick::Error
21
- end
22
- end
23
-
24
- def require_image_processor
25
- if image_processor == :vips
26
- require 'vips' unless defined?(Vips)
27
- else
28
- require 'mini_magick' unless defined?(MiniMagick)
29
- end
14
+ def valid?
15
+ read_image
16
+ true
17
+ rescue InvalidImageError
18
+ false
30
19
  end
31
20
 
32
21
  def metadata
@@ -42,14 +31,31 @@ module ActiveStorageValidations
42
31
  {}
43
32
  end
44
33
 
45
- def valid?
46
- read_image
47
- true
48
- rescue InvalidImageError
49
- false
34
+ private
35
+
36
+ def image_processor
37
+ # Rails returns nil for default image processor, because it is set in an after initiliaze callback
38
+ # https://github.com/rails/rails/blob/89d8569abe2564c8187debf32dd3b4e33d6ad983/activestorage/lib/active_storage/engine.rb
39
+ Rails.application.config.active_storage.variant_processor || DEFAULT_IMAGE_PROCESSOR
50
40
  end
51
41
 
52
- private
42
+ def require_image_processor
43
+ case image_processor
44
+ when :vips then require 'vips' unless defined?(Vips)
45
+ when :mini_magick then require 'mini_magick' unless defined?(MiniMagick)
46
+ end
47
+ end
48
+
49
+ def exception_class
50
+ case image_processor
51
+ when :vips then Vips::Error
52
+ when :mini_magick then MiniMagick::Error
53
+ end
54
+ end
55
+
56
+ def vips_image_processor?
57
+ image_processor == :vips
58
+ end
53
59
 
54
60
  def read_image
55
61
  is_string = file.is_a?(String)
@@ -95,8 +101,16 @@ module ActiveStorageValidations
95
101
  end
96
102
 
97
103
  def new_image_from_path(path)
98
- if image_processor == :vips && defined?(Vips) && (Vips::get_suffixes.include?(File.extname(path).downcase) || !Vips::respond_to?(:vips_foreign_get_suffixes))
99
- Vips::Image.new_from_file(path)
104
+ if vips_image_processor? && (Vips::get_suffixes.include?(File.extname(path).downcase) || !Vips::respond_to?(:vips_foreign_get_suffixes))
105
+ begin
106
+ Vips::Image.new_from_file(path)
107
+ rescue exception_class
108
+ # We handle cases where an error is raised when reading the file
109
+ # because Vips can throw errors rather than returning false
110
+ # We stumble upon this issue while reading 0 byte size file
111
+ # https://github.com/janko/image_processing/issues/97
112
+ false
113
+ end
100
114
  elsif defined?(MiniMagick)
101
115
  MiniMagick::Image.new(path)
102
116
  end
@@ -105,13 +119,13 @@ module ActiveStorageValidations
105
119
  def valid_image?(image)
106
120
  return false unless image
107
121
 
108
- image_processor == :vips && image.is_a?(Vips::Image) ? image.avg : image.valid?
122
+ vips_image_processor? && image.is_a?(Vips::Image) ? image.avg : image.valid?
109
123
  rescue exception_class
110
124
  false
111
125
  end
112
126
 
113
127
  def rotated_image?(image)
114
- if image_processor == :vips && image.is_a?(Vips::Image)
128
+ if vips_image_processor? && image.is_a?(Vips::Image)
115
129
  image.get('exif-ifd0-Orientation').include?('Right-top') ||
116
130
  image.get('exif-ifd0-Orientation').include?('Left-bottom')
117
131
  else
@@ -1,27 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'concerns/errorable.rb'
3
4
  require_relative 'concerns/symbolizable.rb'
4
5
  require_relative 'metadata.rb'
5
6
 
6
7
  module ActiveStorageValidations
7
8
  class ProcessableImageValidator < ActiveModel::EachValidator # :nodoc
8
9
  include OptionProcUnfolding
9
- include ErrorHandler
10
+ include Errorable
10
11
  include Symbolizable
11
12
 
13
+ ERROR_TYPES = %i[
14
+ image_not_processable
15
+ ].freeze
16
+
12
17
  if Rails.gem_version >= Gem::Version.new('6.0.0')
13
18
  def validate_each(record, attribute, _value)
14
19
  return true unless record.send(attribute).attached?
15
20
 
16
- errors_options = initialize_error_options(options)
17
-
18
21
  changes = record.attachment_changes[attribute.to_s]
19
22
  return true if changes.blank?
20
23
 
21
24
  files = Array.wrap(changes.is_a?(ActiveStorage::Attached::Changes::CreateMany) ? changes.attachables : changes.attachable)
22
25
 
23
26
  files.each do |file|
24
- add_error(record, attribute, :image_not_processable, **errors_options) unless Metadata.new(file).valid?
27
+ if !Metadata.new(file).valid?
28
+ errors_options = initialize_error_options(options, file)
29
+ add_error(record, attribute, ERROR_TYPES.first , **errors_options) unless Metadata.new(file).valid?
30
+ end
25
31
  end
26
32
  end
27
33
  else
@@ -32,7 +38,10 @@ module ActiveStorageValidations
32
38
  files = Array.wrap(record.send(attribute))
33
39
 
34
40
  files.each do |file|
35
- add_error(record, attribute, :image_not_processable, **errors_options) unless Metadata.new(file).valid?
41
+ if !Metadata.new(file).valid?
42
+ errors_options = initialize_error_options(options, file)
43
+ add_error(record, attribute, ERROR_TYPES.first , **errors_options) unless Metadata.new(file).valid?
44
+ end
36
45
  end
37
46
  end
38
47
  end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'concerns/errorable.rb'
3
4
  require_relative 'concerns/symbolizable.rb'
4
5
 
5
6
  module ActiveStorageValidations
6
7
  class SizeValidator < ActiveModel::EachValidator # :nodoc:
7
8
  include OptionProcUnfolding
8
- include ErrorHandler
9
+ include Errorable
9
10
  include Symbolizable
10
11
 
11
12
  delegate :number_to_human_size, to: ActiveSupport::NumberHelper
@@ -36,14 +37,12 @@ module ActiveStorageValidations
36
37
  return true unless record.send(attribute).attached?
37
38
 
38
39
  files = Array.wrap(record.send(attribute))
39
-
40
- errors_options = initialize_error_options(options)
41
-
42
40
  flat_options = unfold_procs(record, self.options, AVAILABLE_CHECKS)
43
41
 
44
42
  files.each do |file|
45
- next if content_size_valid?(file.blob.byte_size, flat_options)
43
+ next if is_valid?(file.blob.byte_size, flat_options)
46
44
 
45
+ errors_options = initialize_error_options(options, file)
47
46
  errors_options[:file_size] = number_to_human_size(file.blob.byte_size)
48
47
  errors_options[:min_size] = number_to_human_size(min_size(flat_options))
49
48
  errors_options[:max_size] = number_to_human_size(max_size(flat_options))
@@ -55,7 +54,9 @@ module ActiveStorageValidations
55
54
  end
56
55
  end
57
56
 
58
- def content_size_valid?(file_size, flat_options)
57
+ private
58
+
59
+ def is_valid?(file_size, flat_options)
59
60
  return false if file_size < 0
60
61
 
61
62
  if flat_options[:between].present?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageValidations
4
- VERSION = '1.1.3'
4
+ VERSION = '1.1.4'
5
5
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_model'
4
+ require 'active_support/concern'
4
5
 
5
6
  require 'active_storage_validations/railtie'
6
7
  require 'active_storage_validations/engine'
7
8
  require 'active_storage_validations/option_proc_unfolding'
8
- require 'active_storage_validations/error_handler'
9
9
  require 'active_storage_validations/attached_validator'
10
10
  require 'active_storage_validations/content_type_validator'
11
11
  require 'active_storage_validations/size_validator'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_storage_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-21 00:00:00.000000000 Z
11
+ date: 2023-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -234,14 +234,20 @@ files:
234
234
  - lib/active_storage_validations.rb
235
235
  - lib/active_storage_validations/aspect_ratio_validator.rb
236
236
  - lib/active_storage_validations/attached_validator.rb
237
+ - lib/active_storage_validations/concerns/errorable.rb
237
238
  - lib/active_storage_validations/concerns/symbolizable.rb
238
239
  - lib/active_storage_validations/content_type_validator.rb
239
240
  - lib/active_storage_validations/dimension_validator.rb
240
241
  - lib/active_storage_validations/engine.rb
241
- - lib/active_storage_validations/error_handler.rb
242
242
  - lib/active_storage_validations/limit_validator.rb
243
243
  - lib/active_storage_validations/matchers.rb
244
+ - lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb
244
245
  - lib/active_storage_validations/matchers/attached_validator_matcher.rb
246
+ - lib/active_storage_validations/matchers/concerns/active_storageable.rb
247
+ - lib/active_storage_validations/matchers/concerns/allow_blankable.rb
248
+ - lib/active_storage_validations/matchers/concerns/contextable.rb
249
+ - lib/active_storage_validations/matchers/concerns/messageable.rb
250
+ - lib/active_storage_validations/matchers/concerns/rspecable.rb
245
251
  - lib/active_storage_validations/matchers/concerns/validatable.rb
246
252
  - lib/active_storage_validations/matchers/content_type_validator_matcher.rb
247
253
  - lib/active_storage_validations/matchers/dimension_validator_matcher.rb
@@ -1,21 +0,0 @@
1
- module ActiveStorageValidations
2
- module ErrorHandler
3
-
4
- def initialize_error_options(options)
5
- {
6
- validator_type: self.class.to_sym,
7
- custom_message: (options[:message] if options[:message].present?)
8
- }.compact
9
- end
10
-
11
- def add_error(record, attribute, error_type, **errors_options)
12
- type = errors_options[:custom_message].presence || error_type
13
- return if record.errors.added?(attribute, type)
14
-
15
- # You can read https://api.rubyonrails.org/classes/ActiveModel/Errors.html#method-i-add
16
- # to better understand how Rails model errors work
17
- record.errors.add(attribute, type, **errors_options)
18
- end
19
-
20
- end
21
- end