active_storage_validations 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +56 -18
  3. data/config/locales/da.yml +33 -0
  4. data/config/locales/de.yml +5 -0
  5. data/config/locales/en.yml +5 -0
  6. data/config/locales/es.yml +5 -0
  7. data/config/locales/fr.yml +5 -0
  8. data/config/locales/it.yml +5 -0
  9. data/config/locales/ja.yml +5 -0
  10. data/config/locales/nl.yml +5 -0
  11. data/config/locales/pl.yml +5 -0
  12. data/config/locales/pt-BR.yml +5 -0
  13. data/config/locales/ru.yml +5 -0
  14. data/config/locales/sv.yml +10 -1
  15. data/config/locales/tr.yml +5 -0
  16. data/config/locales/uk.yml +5 -0
  17. data/config/locales/vi.yml +5 -0
  18. data/config/locales/zh-CN.yml +5 -0
  19. data/lib/active_storage_validations/attached_validator.rb +3 -3
  20. data/lib/active_storage_validations/base_size_validator.rb +66 -0
  21. data/lib/active_storage_validations/concerns/errorable.rb +2 -2
  22. data/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +6 -15
  23. data/lib/active_storage_validations/matchers/attached_validator_matcher.rb +5 -13
  24. data/lib/active_storage_validations/matchers/base_size_validator_matcher.rb +134 -0
  25. data/lib/active_storage_validations/matchers/concerns/attachable.rb +48 -0
  26. data/lib/active_storage_validations/matchers/concerns/contextable.rb +20 -8
  27. data/lib/active_storage_validations/matchers/concerns/validatable.rb +9 -3
  28. data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +5 -2
  29. data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +6 -15
  30. data/lib/active_storage_validations/matchers/processable_image_validator_matcher.rb +78 -0
  31. data/lib/active_storage_validations/matchers/size_validator_matcher.rb +4 -139
  32. data/lib/active_storage_validations/matchers/total_size_validator_matcher.rb +40 -0
  33. data/lib/active_storage_validations/matchers.rb +2 -0
  34. data/lib/active_storage_validations/metadata.rb +20 -2
  35. data/lib/active_storage_validations/size_validator.rb +4 -49
  36. data/lib/active_storage_validations/total_size_validator.rb +49 -0
  37. data/lib/active_storage_validations/version.rb +1 -1
  38. data/lib/active_storage_validations.rb +2 -1
  39. metadata +31 -38
@@ -34,7 +34,7 @@ module ActiveStorageValidations
34
34
  private
35
35
 
36
36
  def image_processor
37
- # Rails returns nil for default image processor, because it is set in an after initiliaze callback
37
+ # Rails returns nil for default image processor, because it is set in an after initialize callback
38
38
  # https://github.com/rails/rails/blob/89d8569abe2564c8187debf32dd3b4e33d6ad983/activestorage/lib/active_storage/engine.rb
39
39
  Rails.application.config.active_storage.variant_processor || DEFAULT_IMAGE_PROCESSOR
40
40
  end
@@ -101,7 +101,7 @@ module ActiveStorageValidations
101
101
  end
102
102
 
103
103
  def new_image_from_path(path)
104
- if vips_image_processor? && (Vips::get_suffixes.include?(File.extname(path).downcase) || !Vips::respond_to?(:vips_foreign_get_suffixes))
104
+ if vips_image_processor? && (supported_vips_suffix?(path) || vips_version_below_8_8? || open_uri_tempfile?(path))
105
105
  begin
106
106
  Vips::Image.new_from_file(path)
107
107
  rescue exception_class
@@ -116,6 +116,24 @@ module ActiveStorageValidations
116
116
  end
117
117
  end
118
118
 
119
+ def supported_vips_suffix?(path)
120
+ Vips::get_suffixes.include?(File.extname(path).downcase)
121
+ end
122
+
123
+ def vips_version_below_8_8?
124
+ # FYI, Vips 8.8 was released in 2019
125
+ # https://github.com/libvips/libvips/releases/tag/v8.8.0
126
+ !Vips::respond_to?(:vips_foreign_get_suffixes)
127
+ end
128
+
129
+ def open_uri_tempfile?(path)
130
+ # When trying to open urls for 'large' images, OpenURI will return a
131
+ # tempfile. That tempfile does not have an extension indicating the type
132
+ # of file. However, Vips will be able to process it anyway.
133
+ # The 'large' file value is derived from OpenUri::Buffer class (> 10ko)
134
+ path.split('/').last.starts_with?("open-uri")
135
+ end
136
+
119
137
  def valid_image?(image)
120
138
  return false unless image
121
139
 
@@ -2,22 +2,10 @@
2
2
 
3
3
  require_relative 'concerns/errorable.rb'
4
4
  require_relative 'concerns/symbolizable.rb'
5
+ require_relative 'base_size_validator.rb'
5
6
 
6
7
  module ActiveStorageValidations
7
- class SizeValidator < ActiveModel::EachValidator # :nodoc:
8
- include OptionProcUnfolding
9
- include Errorable
10
- include Symbolizable
11
-
12
- delegate :number_to_human_size, to: ActiveSupport::NumberHelper
13
-
14
- AVAILABLE_CHECKS = %i[
15
- less_than
16
- less_than_or_equal_to
17
- greater_than
18
- greater_than_or_equal_to
19
- between
20
- ].freeze
8
+ class SizeValidator < BaseSizeValidator
21
9
  ERROR_TYPES = %i[
22
10
  file_size_not_less_than
23
11
  file_size_not_less_than_or_equal_to
@@ -26,14 +14,7 @@ module ActiveStorageValidations
26
14
  file_size_not_between
27
15
  ].freeze
28
16
 
29
- def check_validity!
30
- unless AVAILABLE_CHECKS.one? { |argument| options.key?(argument) }
31
- raise ArgumentError, 'You must pass either :less_than(_or_equal_to), :greater_than(_or_equal_to), or :between to the validator'
32
- end
33
- end
34
-
35
17
  def validate_each(record, attribute, _value)
36
- # only attached
37
18
  return true unless record.send(attribute).attached?
38
19
 
39
20
  files = Array.wrap(record.send(attribute))
@@ -43,9 +24,9 @@ module ActiveStorageValidations
43
24
  next if is_valid?(file.blob.byte_size, flat_options)
44
25
 
45
26
  errors_options = initialize_error_options(options, file)
27
+ populate_error_options(errors_options, flat_options)
46
28
  errors_options[:file_size] = number_to_human_size(file.blob.byte_size)
47
- errors_options[:min_size] = number_to_human_size(min_size(flat_options))
48
- errors_options[:max_size] = number_to_human_size(max_size(flat_options))
29
+
49
30
  keys = AVAILABLE_CHECKS & flat_options.keys
50
31
  error_type = "file_size_not_#{keys.first}".to_sym
51
32
 
@@ -53,31 +34,5 @@ module ActiveStorageValidations
53
34
  break
54
35
  end
55
36
  end
56
-
57
- private
58
-
59
- def is_valid?(file_size, flat_options)
60
- return false if file_size < 0
61
-
62
- if flat_options[:between].present?
63
- flat_options[:between].include?(file_size)
64
- elsif flat_options[:less_than].present?
65
- file_size < flat_options[:less_than]
66
- elsif flat_options[:less_than_or_equal_to].present?
67
- file_size <= flat_options[:less_than_or_equal_to]
68
- elsif flat_options[:greater_than].present?
69
- file_size > flat_options[:greater_than]
70
- elsif flat_options[:greater_than_or_equal_to].present?
71
- file_size >= flat_options[:greater_than_or_equal_to]
72
- end
73
- end
74
-
75
- def min_size(flat_options)
76
- flat_options[:between]&.min || flat_options[:greater_than] || flat_options[:greater_than_or_equal_to]
77
- end
78
-
79
- def max_size(flat_options)
80
- flat_options[:between]&.max || flat_options[:less_than] || flat_options[:less_than_or_equal_to]
81
- end
82
37
  end
83
38
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'concerns/errorable.rb'
4
+ require_relative 'concerns/symbolizable.rb'
5
+ require_relative 'base_size_validator.rb'
6
+
7
+ module ActiveStorageValidations
8
+ class TotalSizeValidator < BaseSizeValidator
9
+ ERROR_TYPES = %i[
10
+ total_file_size_not_less_than
11
+ total_file_size_not_less_than_or_equal_to
12
+ total_file_size_not_greater_than
13
+ total_file_size_not_greater_than_or_equal_to
14
+ total_file_size_not_between
15
+ ].freeze
16
+
17
+ def validate_each(record, attribute, _value)
18
+ custom_check_validity!(record, attribute)
19
+
20
+ return true unless record.send(attribute).attached?
21
+
22
+ files = Array.wrap(record.send(attribute))
23
+ flat_options = unfold_procs(record, self.options, AVAILABLE_CHECKS)
24
+
25
+ total_file_size = files.sum { |file| file.blob.byte_size }
26
+
27
+ return true if is_valid?(total_file_size, flat_options)
28
+
29
+ errors_options = initialize_error_options(options, nil)
30
+ populate_error_options(errors_options, flat_options)
31
+ errors_options[:total_file_size] = number_to_human_size(total_file_size)
32
+
33
+ keys = AVAILABLE_CHECKS & flat_options.keys
34
+ error_type = "total_file_size_not_#{keys.first}".to_sym
35
+
36
+ add_error(record, attribute, error_type, **errors_options)
37
+ end
38
+
39
+ private
40
+
41
+ def custom_check_validity!(record, attribute)
42
+ # We can't perform this check in the #check_validity! hook because we do not
43
+ # have enough data (only options & attributes are accessible)
44
+ unless record.send(attribute).is_a?(ActiveStorage::Attached::Many)
45
+ raise ArgumentError, 'This validator is only available for has_many_attached relations'
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageValidations
4
- VERSION = '1.1.4'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -8,11 +8,12 @@ require 'active_storage_validations/engine'
8
8
  require 'active_storage_validations/option_proc_unfolding'
9
9
  require 'active_storage_validations/attached_validator'
10
10
  require 'active_storage_validations/content_type_validator'
11
- require 'active_storage_validations/size_validator'
12
11
  require 'active_storage_validations/limit_validator'
13
12
  require 'active_storage_validations/dimension_validator'
14
13
  require 'active_storage_validations/aspect_ratio_validator'
15
14
  require 'active_storage_validations/processable_image_validator'
15
+ require 'active_storage_validations/size_validator'
16
+ require 'active_storage_validations/total_size_validator'
16
17
 
17
18
  ActiveSupport.on_load(:active_record) do
18
19
  send :include, ActiveStorageValidations
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.4
4
+ version: 1.2.0
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-12-26 00:00:00.000000000 Z
11
+ date: 2024-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: 5.2.0
69
- - !ruby/object:Gem::Dependency
70
- name: minitest-focus
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.4'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.4'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: combustion
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -95,49 +81,49 @@ dependencies:
95
81
  - !ruby/object:Gem::Version
96
82
  version: '1.3'
97
83
  - !ruby/object:Gem::Dependency
98
- name: mini_magick
84
+ name: marcel
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - ">="
102
88
  - !ruby/object:Gem::Version
103
- version: 4.9.5
89
+ version: '0'
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
94
  - - ">="
109
95
  - !ruby/object:Gem::Version
110
- version: 4.9.5
96
+ version: '0'
111
97
  - !ruby/object:Gem::Dependency
112
- name: ruby-vips
98
+ name: mini_magick
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
101
  - - ">="
116
102
  - !ruby/object:Gem::Version
117
- version: 2.1.0
103
+ version: 4.9.5
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - ">="
123
109
  - !ruby/object:Gem::Version
124
- version: 2.1.0
110
+ version: 4.9.5
125
111
  - !ruby/object:Gem::Dependency
126
- name: pry
112
+ name: minitest-focus
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
- - - ">="
115
+ - - "~>"
130
116
  - !ruby/object:Gem::Version
131
- version: '0'
117
+ version: '1.4'
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
- - - ">="
122
+ - - "~>"
137
123
  - !ruby/object:Gem::Version
138
- version: '0'
124
+ version: '1.4'
139
125
  - !ruby/object:Gem::Dependency
140
- name: rubocop
126
+ name: pry
141
127
  requirement: !ruby/object:Gem::Requirement
142
128
  requirements:
143
129
  - - ">="
@@ -151,21 +137,21 @@ dependencies:
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0'
153
139
  - !ruby/object:Gem::Dependency
154
- name: sqlite3
140
+ name: ruby-vips
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
143
  - - ">="
158
144
  - !ruby/object:Gem::Version
159
- version: '0'
145
+ version: 2.1.0
160
146
  type: :development
161
147
  prerelease: false
162
148
  version_requirements: !ruby/object:Gem::Requirement
163
149
  requirements:
164
150
  - - ">="
165
151
  - !ruby/object:Gem::Version
166
- version: '0'
152
+ version: 2.1.0
167
153
  - !ruby/object:Gem::Dependency
168
- name: marcel
154
+ name: simplecov
169
155
  requirement: !ruby/object:Gem::Requirement
170
156
  requirements:
171
157
  - - ">="
@@ -179,7 +165,7 @@ dependencies:
179
165
  - !ruby/object:Gem::Version
180
166
  version: '0'
181
167
  - !ruby/object:Gem::Dependency
182
- name: simplecov
168
+ name: sqlite3
183
169
  requirement: !ruby/object:Gem::Requirement
184
170
  requirements:
185
171
  - - ">="
@@ -193,19 +179,19 @@ dependencies:
193
179
  - !ruby/object:Gem::Version
194
180
  version: '0'
195
181
  - !ruby/object:Gem::Dependency
196
- name: globalid
182
+ name: webmock
197
183
  requirement: !ruby/object:Gem::Requirement
198
184
  requirements:
199
185
  - - ">="
200
186
  - !ruby/object:Gem::Version
201
- version: '0'
187
+ version: '3'
202
188
  type: :development
203
189
  prerelease: false
204
190
  version_requirements: !ruby/object:Gem::Requirement
205
191
  requirements:
206
192
  - - ">="
207
193
  - !ruby/object:Gem::Version
208
- version: '0'
194
+ version: '3'
209
195
  description: Validations for Active Storage (presence)
210
196
  email:
211
197
  - igorkasyanchuk@gmail.com
@@ -216,6 +202,7 @@ files:
216
202
  - MIT-LICENSE
217
203
  - README.md
218
204
  - Rakefile
205
+ - config/locales/da.yml
219
206
  - config/locales/de.yml
220
207
  - config/locales/en.yml
221
208
  - config/locales/es.yml
@@ -234,6 +221,7 @@ files:
234
221
  - lib/active_storage_validations.rb
235
222
  - lib/active_storage_validations/aspect_ratio_validator.rb
236
223
  - lib/active_storage_validations/attached_validator.rb
224
+ - lib/active_storage_validations/base_size_validator.rb
237
225
  - lib/active_storage_validations/concerns/errorable.rb
238
226
  - lib/active_storage_validations/concerns/symbolizable.rb
239
227
  - lib/active_storage_validations/content_type_validator.rb
@@ -243,20 +231,25 @@ files:
243
231
  - lib/active_storage_validations/matchers.rb
244
232
  - lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb
245
233
  - lib/active_storage_validations/matchers/attached_validator_matcher.rb
234
+ - lib/active_storage_validations/matchers/base_size_validator_matcher.rb
246
235
  - lib/active_storage_validations/matchers/concerns/active_storageable.rb
247
236
  - lib/active_storage_validations/matchers/concerns/allow_blankable.rb
237
+ - lib/active_storage_validations/matchers/concerns/attachable.rb
248
238
  - lib/active_storage_validations/matchers/concerns/contextable.rb
249
239
  - lib/active_storage_validations/matchers/concerns/messageable.rb
250
240
  - lib/active_storage_validations/matchers/concerns/rspecable.rb
251
241
  - lib/active_storage_validations/matchers/concerns/validatable.rb
252
242
  - lib/active_storage_validations/matchers/content_type_validator_matcher.rb
253
243
  - lib/active_storage_validations/matchers/dimension_validator_matcher.rb
244
+ - lib/active_storage_validations/matchers/processable_image_validator_matcher.rb
254
245
  - lib/active_storage_validations/matchers/size_validator_matcher.rb
246
+ - lib/active_storage_validations/matchers/total_size_validator_matcher.rb
255
247
  - lib/active_storage_validations/metadata.rb
256
248
  - lib/active_storage_validations/option_proc_unfolding.rb
257
249
  - lib/active_storage_validations/processable_image_validator.rb
258
250
  - lib/active_storage_validations/railtie.rb
259
251
  - lib/active_storage_validations/size_validator.rb
252
+ - lib/active_storage_validations/total_size_validator.rb
260
253
  - lib/active_storage_validations/version.rb
261
254
  - lib/tasks/active_storage_validations_tasks.rake
262
255
  homepage: https://github.com/igorkasyanchuk/active_storage_validations
@@ -272,14 +265,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
272
265
  requirements:
273
266
  - - ">="
274
267
  - !ruby/object:Gem::Version
275
- version: '0'
268
+ version: 2.5.0
276
269
  required_rubygems_version: !ruby/object:Gem::Requirement
277
270
  requirements:
278
271
  - - ">="
279
272
  - !ruby/object:Gem::Version
280
273
  version: '0'
281
274
  requirements: []
282
- rubygems_version: 3.4.10
275
+ rubygems_version: 3.5.11
283
276
  signing_key:
284
277
  specification_version: 4
285
278
  summary: Validations for Active Storage