active_storage_validations 0.9.6 → 0.9.7
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.
- checksums.yaml +4 -4
- data/README.md +16 -3
- data/config/locales/pt-BR.yml +14 -14
- data/lib/active_storage_validations/aspect_ratio_validator.rb +3 -4
- data/lib/active_storage_validations/dimension_validator.rb +0 -2
- data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +12 -2
- data/lib/active_storage_validations/metadata.rb +44 -7
- data/lib/active_storage_validations/version.rb +1 -1
- metadata +34 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f77bdb678731cdb6bb3aca1bddf3a3b1d1d4f34355a778c504931d067f6d0e2
|
4
|
+
data.tar.gz: cb723cb17a4cbfcfec2e7a9b8432ac0d2641afbef327a92e38baa376d15ba2fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d44aed46b1f790d3df1913009fc1c84ea5831be3c8809063c94a0c50de3d8b9f40613eab920c49fb8f81dd0808d9c489aebb1705e022defe1e745d1205a48203
|
7
|
+
data.tar.gz: 3d770860efb253f13ea1f18086c5b8a51253caf69875ba1d9d7921c17b9c5ce43f8001f4d8eeb1e095f8f37d1f0924dbddcdb35ca24b721d6fd5cf2a002d9a90
|
data/README.md
CHANGED
@@ -26,16 +26,17 @@ For example you have a model like this and you want to add validation.
|
|
26
26
|
class User < ApplicationRecord
|
27
27
|
has_one_attached :avatar
|
28
28
|
has_many_attached :photos
|
29
|
+
has_one_attached :image
|
29
30
|
|
30
31
|
validates :name, presence: true
|
31
32
|
|
32
33
|
validates :avatar, attached: true, content_type: 'image/png',
|
33
34
|
dimension: { width: 200, height: 200 }
|
34
|
-
validates :photos, attached: true, content_type: ['image/png', 'image/
|
35
|
+
validates :photos, attached: true, content_type: ['image/png', 'image/jpeg'],
|
35
36
|
dimension: { width: { min: 800, max: 2400 },
|
36
37
|
height: { min: 600, max: 1800 }, message: 'is not given between dimension' }
|
37
38
|
validates :image, attached: true,
|
38
|
-
content_type: ['image/png', 'image/
|
39
|
+
content_type: ['image/png', 'image/jpeg'],
|
39
40
|
aspect_ratio: :landscape
|
40
41
|
end
|
41
42
|
```
|
@@ -44,13 +45,15 @@ or
|
|
44
45
|
|
45
46
|
```ruby
|
46
47
|
class Project < ApplicationRecord
|
48
|
+
has_one_attached :logo
|
47
49
|
has_one_attached :preview
|
48
50
|
has_one_attached :attachment
|
49
51
|
has_many_attached :documents
|
50
52
|
|
51
53
|
validates :title, presence: true
|
52
54
|
|
53
|
-
validates :
|
55
|
+
validates :logo, attached: true, size: { less_than: 100.megabytes , message: 'is too large' }
|
56
|
+
validates :preview, attached: true, size: { between: 1.kilobyte..100.megabytes , message: 'is not given between size' }
|
54
57
|
validates :attachment, attached: true, content_type: { in: 'application/pdf', message: 'is not a PDF' }
|
55
58
|
validates :documents, limit: { min: 1, max: 3 }
|
56
59
|
end
|
@@ -177,6 +180,8 @@ gem 'active_storage_validations'
|
|
177
180
|
|
178
181
|
# Optional, to use :dimension validator or :aspect_ratio validator
|
179
182
|
gem 'mini_magick', '>= 4.9.5'
|
183
|
+
# Or
|
184
|
+
gem 'ruby-vips', '>= 2.1.0'
|
180
185
|
```
|
181
186
|
|
182
187
|
And then execute:
|
@@ -301,10 +306,12 @@ Snippet to run in console:
|
|
301
306
|
BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle
|
302
307
|
BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle
|
303
308
|
BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle
|
309
|
+
BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle
|
304
310
|
BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle
|
305
311
|
BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test
|
306
312
|
BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test
|
307
313
|
BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test
|
314
|
+
BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle exec rake test
|
308
315
|
BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test
|
309
316
|
```
|
310
317
|
|
@@ -362,6 +369,12 @@ You are welcome to contribute.
|
|
362
369
|
- https://github.com/vietqhoang
|
363
370
|
- https://github.com/kemenaran
|
364
371
|
- https://github.com/jrmhaig
|
372
|
+
- https://github.com/tagliala
|
373
|
+
- https://github.com/evedovelli
|
374
|
+
- https://github.com/JuanVqz
|
375
|
+
- https://github.com/luiseugenio
|
376
|
+
- https://github.com/equivalent
|
377
|
+
- https://github.com/NARKOZ
|
365
378
|
|
366
379
|
## License
|
367
380
|
|
data/config/locales/pt-BR.yml
CHANGED
@@ -2,21 +2,21 @@ pt-BR:
|
|
2
2
|
errors:
|
3
3
|
messages:
|
4
4
|
content_type_invalid: "tem um tipo de arquivo inválido"
|
5
|
-
file_size_out_of_range: "tamanho %{file_size} está fora da faixa de tamanho válida"
|
6
|
-
limit_out_of_range: "número total está fora do limite"
|
5
|
+
file_size_out_of_range: "tem tamanho %{file_size} e está fora da faixa de tamanho válida"
|
6
|
+
limit_out_of_range: "o número total está fora do limite"
|
7
7
|
image_metadata_missing: "não é uma imagem válida"
|
8
|
-
dimension_min_inclusion: "deve ser maior ou igual a %{width} x %{height}
|
9
|
-
dimension_max_inclusion: "deve ser menor ou igual a %{width} x %{height}
|
10
|
-
dimension_width_inclusion: "
|
11
|
-
dimension_height_inclusion: "
|
12
|
-
dimension_width_greater_than_or_equal_to: "
|
13
|
-
dimension_height_greater_than_or_equal_to: "
|
14
|
-
dimension_width_less_than_or_equal_to: "
|
15
|
-
dimension_height_less_than_or_equal_to: "
|
16
|
-
dimension_width_equal_to: "
|
17
|
-
dimension_height_equal_to: "
|
8
|
+
dimension_min_inclusion: "deve ser maior ou igual a %{width} x %{height} pixels"
|
9
|
+
dimension_max_inclusion: "deve ser menor ou igual a %{width} x %{height} pixels"
|
10
|
+
dimension_width_inclusion: "deve ter largura entre %{min} e %{max} pixels"
|
11
|
+
dimension_height_inclusion: "deve ter altura entre %{min} e %{max} pixels"
|
12
|
+
dimension_width_greater_than_or_equal_to: "deve ter largura maior ou igual a %{length} pixels"
|
13
|
+
dimension_height_greater_than_or_equal_to: "deve ter altura maior ou igual a %{length} pixels"
|
14
|
+
dimension_width_less_than_or_equal_to: "deve ter largura menor ou igual a %{length} pixels"
|
15
|
+
dimension_height_less_than_or_equal_to: "deve ter altura menor ou igual a %{length} pixels"
|
16
|
+
dimension_width_equal_to: "deve ter largura igual a %{length} pixels"
|
17
|
+
dimension_height_equal_to: "deve ter altura igual a %{length} pixels"
|
18
18
|
aspect_ratio_not_square: "não é uma imagem quadrada"
|
19
|
-
aspect_ratio_not_portrait: "não
|
20
|
-
aspect_ratio_not_landscape: "não
|
19
|
+
aspect_ratio_not_portrait: "não está no formato retrato"
|
20
|
+
aspect_ratio_not_landscape: "não está no formato paisagem"
|
21
21
|
aspect_ratio_is_not: "não contém uma proporção de %{aspect_ratio}"
|
22
22
|
aspect_ratio_unknown: "não tem uma proporção definida"
|
@@ -8,7 +8,6 @@ module ActiveStorageValidations
|
|
8
8
|
PRECISION = 3
|
9
9
|
|
10
10
|
def initialize(options)
|
11
|
-
require 'mini_magick' unless defined?(MiniMagick)
|
12
11
|
super(options)
|
13
12
|
end
|
14
13
|
|
@@ -37,14 +36,14 @@ module ActiveStorageValidations
|
|
37
36
|
# Rails 5
|
38
37
|
def validate_each(record, attribute, _value)
|
39
38
|
return true unless record.send(attribute).attached?
|
40
|
-
|
39
|
+
|
41
40
|
files = Array.wrap(record.send(attribute))
|
42
|
-
|
41
|
+
|
43
42
|
files.each do |file|
|
44
43
|
# Analyze file first if not analyzed to get all required metadata.
|
45
44
|
file.analyze; file.reload unless file.analyzed?
|
46
45
|
metadata = file.metadata
|
47
|
-
|
46
|
+
|
48
47
|
next if is_valid?(record, attribute, metadata)
|
49
48
|
break
|
50
49
|
end
|
@@ -7,8 +7,6 @@ module ActiveStorageValidations
|
|
7
7
|
AVAILABLE_CHECKS = %i[width height min max].freeze
|
8
8
|
|
9
9
|
def initialize(options)
|
10
|
-
require 'mini_magick' unless defined?(MiniMagick)
|
11
|
-
|
12
10
|
[:width, :height].each do |length|
|
13
11
|
if options[length] and options[length].is_a?(Hash)
|
14
12
|
if range = options[length][:in]
|
@@ -35,7 +35,7 @@ module ActiveStorageValidations
|
|
35
35
|
def failure_message
|
36
36
|
<<~MESSAGE
|
37
37
|
Expected #{@attribute_name}
|
38
|
-
|
38
|
+
|
39
39
|
Accept content types: #{allowed_types.join(", ")}
|
40
40
|
#{accepted_types_and_failures}
|
41
41
|
|
@@ -57,7 +57,7 @@ module ActiveStorageValidations
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def rejected_types
|
60
|
-
@rejected_types || (
|
60
|
+
@rejected_types || (content_type_keys - allowed_types)
|
61
61
|
end
|
62
62
|
|
63
63
|
def allowed_types_allowed?
|
@@ -96,6 +96,16 @@ module ActiveStorageValidations
|
|
96
96
|
suffix = type.to_s.split('/').last
|
97
97
|
{ io: Tempfile.new('.'), filename: "test.#{suffix}", content_type: type }
|
98
98
|
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def content_type_keys
|
103
|
+
if Rails.gem_version < Gem::Version.new('6.1.0')
|
104
|
+
Mime::LOOKUP.keys
|
105
|
+
else
|
106
|
+
Marcel::TYPES.keys
|
107
|
+
end
|
108
|
+
end
|
99
109
|
end
|
100
110
|
end
|
101
111
|
end
|
@@ -3,9 +3,22 @@ module ActiveStorageValidations
|
|
3
3
|
attr_reader :file
|
4
4
|
|
5
5
|
def initialize(file)
|
6
|
+
require_image_processor
|
6
7
|
@file = file
|
7
8
|
end
|
8
9
|
|
10
|
+
def image_processor
|
11
|
+
Rails.application.config.active_storage.variant_processor
|
12
|
+
end
|
13
|
+
|
14
|
+
def require_image_processor
|
15
|
+
if image_processor == :vips
|
16
|
+
require 'vips' unless defined?(Vips)
|
17
|
+
else
|
18
|
+
require 'mini_magick' unless defined?(MiniMagick)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
9
22
|
def metadata
|
10
23
|
read_image do |image|
|
11
24
|
if rotated_image?(image)
|
@@ -42,29 +55,53 @@ module ActiveStorageValidations
|
|
42
55
|
tempfile.flush
|
43
56
|
tempfile.rewind
|
44
57
|
|
45
|
-
image =
|
58
|
+
image = if image_processor == :vips && Vips::get_suffixes.include?(File.extname(tempfile.path))
|
59
|
+
Vips::Image.new_from_file(tempfile.path)
|
60
|
+
else
|
61
|
+
MiniMagick::Image.new(tempfile.path)
|
62
|
+
end
|
46
63
|
else
|
47
|
-
image =
|
64
|
+
image = if image_processor == :vips && Vips::get_suffixes.include?(File.extname(read_file_path))
|
65
|
+
Vips::Image.new_from_file(read_file_path)
|
66
|
+
else
|
67
|
+
MiniMagick::Image.new(read_file_path)
|
68
|
+
end
|
48
69
|
end
|
49
70
|
|
50
|
-
if image
|
71
|
+
if image && valid_image?(image)
|
51
72
|
yield image
|
52
73
|
else
|
53
|
-
logger.info "Skipping image analysis because ImageMagick doesn't support the file"
|
74
|
+
logger.info "Skipping image analysis because ImageMagick or Vips doesn't support the file"
|
54
75
|
{}
|
55
76
|
end
|
56
|
-
rescue LoadError
|
57
|
-
logger.info "Skipping image analysis because the mini_magick gem isn't installed"
|
77
|
+
rescue LoadError, NameError
|
78
|
+
logger.info "Skipping image analysis because the mini_magick or ruby-vips gem isn't installed"
|
58
79
|
{}
|
59
80
|
rescue MiniMagick::Error => error
|
60
81
|
logger.error "Skipping image analysis due to an ImageMagick error: #{error.message}"
|
61
82
|
{}
|
83
|
+
rescue Vips::Error => error
|
84
|
+
logger.error "Skipping image analysis due to a Vips error: #{error.message}"
|
85
|
+
{}
|
62
86
|
ensure
|
63
87
|
image = nil
|
64
88
|
end
|
65
89
|
|
90
|
+
def valid_image?(image)
|
91
|
+
image_processor == :vips ? image.avg : image.valid?
|
92
|
+
rescue Vips::Error
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
66
96
|
def rotated_image?(image)
|
67
|
-
|
97
|
+
if image_processor == :vips
|
98
|
+
image.get('exif-ifd0-Orientation').include?('Right-top') ||
|
99
|
+
image.get('exif-ifd0-Orientation').include?('Left-bottom')
|
100
|
+
else
|
101
|
+
%w[ RightTop LeftBottom ].include?(image["%[orientation]"])
|
102
|
+
end
|
103
|
+
rescue Vips::Error # field "exif-ifd0-Orientation" not found
|
104
|
+
false
|
68
105
|
end
|
69
106
|
|
70
107
|
def read_file_path
|
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: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Kasyanchuk
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 4.9.5
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ruby-vips
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.1.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 2.1.0
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: pry
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +150,20 @@ dependencies:
|
|
136
150
|
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: marcel
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
139
167
|
description: Validations for Active Storage (presence)
|
140
168
|
email:
|
141
169
|
- igorkasyanchuk@gmail.com
|
@@ -180,7 +208,7 @@ homepage: https://github.com/igorkasyanchuk/active_storage_validations
|
|
180
208
|
licenses:
|
181
209
|
- MIT
|
182
210
|
metadata: {}
|
183
|
-
post_install_message:
|
211
|
+
post_install_message:
|
184
212
|
rdoc_options: []
|
185
213
|
require_paths:
|
186
214
|
- lib
|
@@ -195,8 +223,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
195
223
|
- !ruby/object:Gem::Version
|
196
224
|
version: '0'
|
197
225
|
requirements: []
|
198
|
-
rubygems_version: 3.
|
199
|
-
signing_key:
|
226
|
+
rubygems_version: 3.2.3
|
227
|
+
signing_key:
|
200
228
|
specification_version: 4
|
201
229
|
summary: Validations for Active Storage
|
202
230
|
test_files: []
|