active_storage_validations 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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