active_storage_validations 0.8.8 → 0.9.6
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 +42 -6
- data/config/locales/de.yml +13 -8
- data/config/locales/en.yml +0 -0
- data/config/locales/es.yml +22 -0
- data/config/locales/it.yml +22 -0
- data/config/locales/nl.yml +22 -0
- data/config/locales/pl.yml +22 -0
- data/config/locales/ru.yml +0 -0
- data/config/locales/tr.yml +22 -0
- data/config/locales/uk.yml +19 -19
- data/config/locales/vi.yml +22 -0
- data/lib/active_storage_validations/aspect_ratio_validator.rb +1 -1
- data/lib/active_storage_validations/attached_validator.rb +4 -1
- data/lib/active_storage_validations/content_type_validator.rb +12 -7
- data/lib/active_storage_validations/dimension_validator.rb +6 -6
- data/lib/active_storage_validations/limit_validator.rb +1 -1
- data/lib/active_storage_validations/matchers/attached_validator_matcher.rb +17 -10
- data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +8 -2
- data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +16 -2
- data/lib/active_storage_validations/matchers/size_validator_matcher.rb +7 -1
- data/lib/active_storage_validations/matchers.rb +1 -1
- data/lib/active_storage_validations/metadata.rb +10 -1
- data/lib/active_storage_validations/size_validator.rb +12 -1
- data/lib/active_storage_validations/version.rb +1 -1
- data/lib/active_storage_validations.rb +0 -0
- metadata +62 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52bbd6249bbadd7549ccd7daf17673e98ccfd757b15ec954b67c5d7ce3395c84
|
4
|
+
data.tar.gz: cf3664efb821cd7fe60b0536e0d394f900af6fb128161ab13d62d373b2018013
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bece2608d56156a83e468ffaf4ed31dead1769882457c1ff8480586ce0335122b475084f24f914d4d8083c5b4f2b891bda7465b25b2d34272ba76631c313167f
|
7
|
+
data.tar.gz: 56a1cbb1bd5bddc4cce887405eecd6d5e27cc9bfcdca97e636ccf43cf98ce29d9077e1b3e7a602dcb229cd24d25125024c4d83beba6f82050edc773b32d21ca4
|
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# Active Storage Validations
|
2
2
|
|
3
|
-
|
3
|
+
[](https://github.com/igorkasyanchuk/active_storage_validations/actions)
|
4
|
+
[](https://www.railsjazz.com)
|
5
|
+
[](https://www.patreon.com/igorkasyanchuk)
|
4
6
|
|
5
|
-
|
7
|
+
If you are using `active_storage` gem and you want to add simple validations for it, like presence or content_type you need to write a custom validation method.
|
6
8
|
|
7
|
-
|
9
|
+
This gems doing it for you. Just use `attached: true` or `content_type: 'image/png'` validation.
|
8
10
|
|
9
11
|
## What it can do
|
10
12
|
|
@@ -56,14 +58,15 @@ end
|
|
56
58
|
|
57
59
|
### More examples
|
58
60
|
|
59
|
-
- Content type validation using symbols. In order to infer the correct mime type from the symbol, the types must be registered with `
|
61
|
+
- Content type validation using symbols. In order to infer the correct mime type from the symbol, the types must be registered with `Marcel::EXTENSIONS` (`MimeMagic::EXTENSIONS` for Rails <= 6.1.3).
|
60
62
|
|
61
63
|
```ruby
|
62
64
|
class User < ApplicationRecord
|
63
65
|
has_one_attached :avatar
|
64
66
|
has_many_attached :photos
|
65
67
|
|
66
|
-
validates :avatar, attached: true, content_type: :png #
|
68
|
+
validates :avatar, attached: true, content_type: :png # Marcel::Magic.by_extension(:png).to_s => 'image/png'
|
69
|
+
# Rails <= 6.1.3; MimeMagic.by_extension(:png).to_s => 'image/png'
|
67
70
|
# or
|
68
71
|
validates :photos, attached: true, content_type: [:png, :jpg, :jpeg]
|
69
72
|
# or
|
@@ -218,6 +221,7 @@ describe User do
|
|
218
221
|
|
219
222
|
it { is_expected.to validate_dimensions_of(:avatar).width(250) }
|
220
223
|
it { is_expected.to validate_dimensions_of(:avatar).height(200) }
|
224
|
+
it { is_expected.to validate_dimensions_of(:avatar).width(250).height(200).with_message('Invalid dimensions.') }
|
221
225
|
it { is_expected.to validate_dimensions_of(:avatar).width_min(200) }
|
222
226
|
it { is_expected.to validate_dimensions_of(:avatar).width_max(500) }
|
223
227
|
it { is_expected.to validate_dimensions_of(:avatar).height_min(100) }
|
@@ -259,6 +263,7 @@ class UserTest < ActiveSupport::TestCase
|
|
259
263
|
|
260
264
|
should validate_dimensions_of(:avatar).width(250)
|
261
265
|
should validate_dimensions_of(:avatar).height(200)
|
266
|
+
should validate_dimensions_of(:avatar).width(250).height(200).with_message('Invalid dimensions.')
|
262
267
|
should validate_dimensions_of(:avatar).width_min(200)
|
263
268
|
should validate_dimensions_of(:avatar).width_max(500)
|
264
269
|
should validate_dimensions_of(:avatar).height_min(100)
|
@@ -287,8 +292,21 @@ To run tests in root folder of gem:
|
|
287
292
|
|
288
293
|
* `BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test` to run for Rails 5.2
|
289
294
|
* `BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test` to run for Rails 6.0
|
295
|
+
* `BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test` to run for Rails 6.1
|
296
|
+
* `BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test` to run for Rails main branch
|
290
297
|
|
291
|
-
|
298
|
+
Snippet to run in console:
|
299
|
+
|
300
|
+
```
|
301
|
+
BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle
|
302
|
+
BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle
|
303
|
+
BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle
|
304
|
+
BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle
|
305
|
+
BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test
|
306
|
+
BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test
|
307
|
+
BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test
|
308
|
+
BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test
|
309
|
+
```
|
292
310
|
|
293
311
|
## Known issues
|
294
312
|
|
@@ -329,7 +347,25 @@ You are welcome to contribute.
|
|
329
347
|
- https://github.com/willnet
|
330
348
|
- https://github.com/mohanklein
|
331
349
|
- https://github.com/High5Apps
|
350
|
+
- https://github.com/mschnitzer
|
351
|
+
- https://github.com/sinankeskin
|
352
|
+
- https://github.com/alejandrodevs
|
353
|
+
- https://github.com/molfar
|
354
|
+
- https://github.com/connorshea
|
355
|
+
- https://github.com/yshmarov
|
356
|
+
- https://github.com/fongfan999
|
357
|
+
- https://github.com/cooperka
|
358
|
+
- https://github.com/dolarsrg
|
359
|
+
- https://github.com/jayshepherd
|
360
|
+
- https://github.com/ohbarye
|
361
|
+
- https://github.com/randsina
|
362
|
+
- https://github.com/vietqhoang
|
363
|
+
- https://github.com/kemenaran
|
364
|
+
- https://github.com/jrmhaig
|
332
365
|
|
333
366
|
## License
|
334
367
|
|
335
368
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
369
|
+
|
370
|
+
[<img src="https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true"
|
371
|
+
/>](https://www.railsjazz.com/)
|
data/config/locales/de.yml
CHANGED
@@ -2,16 +2,21 @@ de:
|
|
2
2
|
errors:
|
3
3
|
messages:
|
4
4
|
content_type_invalid: "hat einen ungültigen Dateityp"
|
5
|
-
file_size_out_of_range: "Dateigröße
|
5
|
+
file_size_out_of_range: "Dateigröße %{file_size} liegt nicht im erlaubten Bereich"
|
6
6
|
limit_out_of_range: "Anzahl ist außerhalb des gültigen Bereichs"
|
7
|
-
image_metadata_missing: "ist
|
7
|
+
image_metadata_missing: "ist kein gültiges Bild"
|
8
8
|
dimension_min_inclusion: "muss größer oder gleich %{width} x %{height} Pixel sein"
|
9
9
|
dimension_max_inclusion: "muss kleiner oder gleich %{width} x %{height} Pixel sein"
|
10
|
-
dimension_width_inclusion: "
|
11
|
-
dimension_height_inclusion: "
|
12
|
-
dimension_width_greater_than_or_equal_to: "
|
13
|
-
dimension_height_greater_than_or_equal_to: "
|
10
|
+
dimension_width_inclusion: "Bildbreite muss zwischen %{min} und %{max} Pixel liegen"
|
11
|
+
dimension_height_inclusion: "Bildhöhe muss zwischen %{min} und %{max} Pixel liegen"
|
12
|
+
dimension_width_greater_than_or_equal_to: "Bildbreite muss größer oder gleich %{length} Pixel sein"
|
13
|
+
dimension_height_greater_than_or_equal_to: "Bildhöhe muss größer oder gleich %{length} Pixel sein"
|
14
14
|
dimension_width_less_than_or_equal_to: "Breite muss kleiner oder gleich %{length} Pixel sein"
|
15
15
|
dimension_height_less_than_or_equal_to: "Höhe muss kleiner oder gleich %{length} Pixel sein"
|
16
|
-
dimension_width_equal_to: "
|
17
|
-
dimension_height_equal_to: "
|
16
|
+
dimension_width_equal_to: "Bildbreite muss genau %{length} Pixel sein"
|
17
|
+
dimension_height_equal_to: "Bildhöhe muss genau %{length} Pixel sein"
|
18
|
+
aspect_ratio_not_square: "muss quadratisch sein"
|
19
|
+
aspect_ratio_not_portrait: "muss Hochformat sein"
|
20
|
+
aspect_ratio_not_landscape: "muss Querformat sein"
|
21
|
+
aspect_ratio_is_not: "muss ein Bildseitenverhältnis von %{aspect_ratio} haben"
|
22
|
+
aspect_ratio_unknown: "hat ein unbekanntes Bildseitenverhältnis"
|
data/config/locales/en.yml
CHANGED
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
es:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid: "tiene un tipo de contenido inválido"
|
5
|
+
file_size_out_of_range: "tamaño %{file_size} no está entre el rango requerido"
|
6
|
+
limit_out_of_range: "el número total está fuera de rango"
|
7
|
+
image_metadata_missing: "no es una imagen válida"
|
8
|
+
dimension_min_inclusion: "debe ser mayor o igual a %{width} x %{height} pixel"
|
9
|
+
dimension_max_inclusion: "debe ser menor o igual a %{width} x %{height} pixel"
|
10
|
+
dimension_width_inclusion: "el ancho no se incluye entre %{min} y %{max} pixel"
|
11
|
+
dimension_height_inclusion: "la altura no se incluye entre %{min} y %{max} pixel"
|
12
|
+
dimension_width_greater_than_or_equal_to: "el ancho debe ser mayor o igual a %{length} pixel"
|
13
|
+
dimension_height_greater_than_or_equal_to: "la altura debe ser mayor o igual a %{length} pixel"
|
14
|
+
dimension_width_less_than_or_equal_to: "el ancho debe ser menor o igual a %{length} pixel"
|
15
|
+
dimension_height_less_than_or_equal_to: "la altura debe ser menor o igual a %{length} pixel"
|
16
|
+
dimension_width_equal_to: "el ancho debe ser igual a %{length} pixel"
|
17
|
+
dimension_height_equal_to: "la altura debe ser igual a %{length} pixel"
|
18
|
+
aspect_ratio_not_square: "debe ser una imagen cuadrada"
|
19
|
+
aspect_ratio_not_portrait: "debe ser una imagen vertical"
|
20
|
+
aspect_ratio_not_landscape: "debe ser una imagen apaisada"
|
21
|
+
aspect_ratio_is_not: "debe tener una relación de aspecto de %{aspect_ratio}"
|
22
|
+
aspect_ratio_unknown: "tiene una relación de aspecto desconocida"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
it:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid: "ha un tipo di contenuto non valido"
|
5
|
+
file_size_out_of_range: "la dimensione del file %{file_size} non è compresa nell’intervallo consentito"
|
6
|
+
limit_out_of_range: "il valore è al di fuori dell’intervallo consentito"
|
7
|
+
image_metadata_missing: "non è un'immagine valida"
|
8
|
+
dimension_min_inclusion: "deve essere maggiore o uguale a %{width} x %{height} pixel"
|
9
|
+
dimension_max_inclusion: "deve essere minore o uguale a %{width} x %{height} pixel"
|
10
|
+
dimension_width_inclusion: "la larghezza deve essere compresa tra %{min} e %{max} pixel"
|
11
|
+
dimension_height_inclusion: "l’altezza deve essere compresa tra %{min} e %{max} pixel"
|
12
|
+
dimension_width_greater_than_or_equal_to: "la larghezza deve essere maggiore o uguale a %{length} pixel"
|
13
|
+
dimension_height_greater_than_or_equal_to: "l’altezza deve essere maggiore o uguale a %{length} pixel"
|
14
|
+
dimension_width_less_than_or_equal_to: "la larghezza deve essere minore o uguale a %{length} pixel"
|
15
|
+
dimension_height_less_than_or_equal_to: "l’altezza deve essere minore o uguale a %{length} pixel"
|
16
|
+
dimension_width_equal_to: "la larghezza deve essere pari a %{length} pixel"
|
17
|
+
dimension_height_equal_to: "l’altezza deve essere pari a %{length} pixel"
|
18
|
+
aspect_ratio_not_square: "deve essere un’immagine quadrata"
|
19
|
+
aspect_ratio_not_portrait: "l’orientamento dell’immagine deve essere verticale"
|
20
|
+
aspect_ratio_not_landscape: "l’orientamento dell’immagine deve essere orizzontale"
|
21
|
+
aspect_ratio_is_not: "deve avere un rapporto altezza / larghezza di %{aspect_ratio}"
|
22
|
+
aspect_ratio_unknown: "ha un rapporto altezza / larghezza sconosciuto"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
nl:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid: "heeft een ongeldig inhoudstype"
|
5
|
+
file_size_out_of_range: "bestandsgrootte %{file_size} valt niet tussen het vereiste bereik"
|
6
|
+
limit_out_of_range: "totaal aantal valt buiten het vereiste bereik"
|
7
|
+
image_metadata_missing: "is geen geldige afbeelding"
|
8
|
+
dimension_min_inclusion: "moet groter of gelijk zijn aan %{width} x %{height} pixels"
|
9
|
+
dimension_max_inclusion: "moet kleiner of gelijk zijn aan %{width} x %{height} pixels"
|
10
|
+
dimension_width_inclusion: "breedte niet tussen de %{min} en %{max} pixels"
|
11
|
+
dimension_height_inclusion: "hoogte niet tussen de %{min} en %{max} pixels"
|
12
|
+
dimension_width_greater_than_or_equal_to: "breedte moet groter of gelijk zijn aan %{length} pixels"
|
13
|
+
dimension_height_greater_than_or_equal_to: "hoogte moet groter of gelijk zijn aan %{length} pixels"
|
14
|
+
dimension_width_less_than_or_equal_to: "breedte moet kleiner of gelijk zijn aan %{length} pixels"
|
15
|
+
dimension_height_less_than_or_equal_to: "hoogte moet kleiner of gelijk zijn aan %{length} pixels"
|
16
|
+
dimension_width_equal_to: "breedte moet gelijk zijn aan %{length} pixels"
|
17
|
+
dimension_height_equal_to: "hoogte moet gelijk zijn aan %{length} pixels"
|
18
|
+
aspect_ratio_not_square: "moet een vierkante afbeelding zijn"
|
19
|
+
aspect_ratio_not_portrait: "moet een staande afbeelding zijn"
|
20
|
+
aspect_ratio_not_landscape: "moet een liggende afbeelding zijn"
|
21
|
+
aspect_ratio_is_not: "moet een beeldverhouding hebben van %{aspect_ratio}"
|
22
|
+
aspect_ratio_unknown: "heeft een onbekende beeldverhouding"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
pl:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid: "jest nieprawidłowego typu"
|
5
|
+
file_size_out_of_range: "rozmiar %{file_size} nie zawiera się w dopuszczalnym zakresie"
|
6
|
+
limit_out_of_range: "ilość przekracza dopuszczalny zakres"
|
7
|
+
image_metadata_missing: "nie jest prawidłowym obrazem"
|
8
|
+
dimension_min_inclusion: "musi być równe lub większe od %{width} x %{height} pixeli"
|
9
|
+
dimension_max_inclusion: "musi być równe lub mniejsze od %{width} x %{height} pixeli"
|
10
|
+
dimension_width_inclusion: "szerokość musi wynosić od %{min} do %{max} pixeli"
|
11
|
+
dimension_height_inclusion: "wysokość musi wynosić od %{min} do %{max} pixeli"
|
12
|
+
dimension_width_greater_than_or_equal_to: "szerokość musi mieć co najmniej %{length} pixeli"
|
13
|
+
dimension_height_greater_than_or_equal_to: "wysokość musi mieć co najmniej %{length} pixeli"
|
14
|
+
dimension_width_less_than_or_equal_to: "szerokość musi mieć co najwyżej %{length} pixeli"
|
15
|
+
dimension_height_less_than_or_equal_to: "wysokość musi mieć co najwyżej %{length} pixeli"
|
16
|
+
dimension_width_equal_to: "szerokość musi wynosić %{length} pixeli"
|
17
|
+
dimension_height_equal_to: "wysokość musi wynosić %{length} pixeli"
|
18
|
+
aspect_ratio_not_square: "musi mieć proporcje kwadratu"
|
19
|
+
aspect_ratio_not_portrait: "musi mieć proporcje portretu"
|
20
|
+
aspect_ratio_not_landscape: "musi mieć proporcje pejzażu"
|
21
|
+
aspect_ratio_is_not: "musi mieć proporcje %{aspect_ratio}"
|
22
|
+
aspect_ratio_unknown: "ma nieokreślone proporcje"
|
data/config/locales/ru.yml
CHANGED
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
tr:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid: "geçersiz dosya tipine sahip"
|
5
|
+
file_size_out_of_range: "dosya boyutu %{file_size} gerekli aralık dışında"
|
6
|
+
limit_out_of_range: "toplam miktar aralık dışında"
|
7
|
+
image_metadata_missing: "geçerli bir imaj değil"
|
8
|
+
dimension_min_inclusion: "%{width} x %{height} piksele eşit ya da büyük olmalı"
|
9
|
+
dimension_max_inclusion: "%{width} x %{height} piksele eşit ya da küçük olmalı"
|
10
|
+
dimension_width_inclusion: "en %{min} ve %{max} piksel aralığı dışında"
|
11
|
+
dimension_height_inclusion: "boy %{min} ve %{max} piksel aralığı dışında"
|
12
|
+
dimension_width_greater_than_or_equal_to: "en %{length} piksele eşit ya da büyük olmalı"
|
13
|
+
dimension_height_greater_than_or_equal_to: "boy %{length} piksele eşit ya da büyük olmalı"
|
14
|
+
dimension_width_less_than_or_equal_to: "en %{length} piksele eşit ya da küçük olmalı"
|
15
|
+
dimension_height_less_than_or_equal_to: "boy %{length} piksele eşit ya da küçük olmalı"
|
16
|
+
dimension_width_equal_to: "en %{length} piksele eşit olmalı"
|
17
|
+
dimension_height_equal_to: "boy %{length} piksele eşit olmalı"
|
18
|
+
aspect_ratio_not_square: "kare bir imaj olmalı"
|
19
|
+
aspect_ratio_not_portrait: "dikey bir imaj olmalı"
|
20
|
+
aspect_ratio_not_landscape: "yatay bir imaj olmalı"
|
21
|
+
aspect_ratio_is_not: "%{aspect_ratio} en boy oranına sahip olmalı"
|
22
|
+
aspect_ratio_unknown: "bilinmeyen en boy oranı"
|
data/config/locales/uk.yml
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
uk:
|
2
2
|
errors:
|
3
3
|
messages:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
4
|
+
content_type_invalid: "має неприпустимий тип вмісту"
|
5
|
+
file_size_out_of_range: "розмір %{file_size} більше необхідного"
|
6
|
+
limit_out_of_range: "кількість файлів більше необхідного"
|
7
|
+
image_metadata_missing: "не є допустимим зображенням"
|
8
|
+
dimension_min_inclusion: "мусить бути більше або дорівнювати %{width} x %{height} пікселям"
|
9
|
+
dimension_max_inclusion: "мусить бути менше або дорівнювати %{width} x %{height} пікселям"
|
10
|
+
dimension_width_inclusion: "ширина не включена між %{min} і %{max} пікселям"
|
11
|
+
dimension_height_inclusion: "висота не включена між %{min} і %{max} пікселям"
|
12
|
+
dimension_width_greater_than_or_equal_to: "ширина мусить бути більше або дорівнювати %{length} пікселям"
|
13
|
+
dimension_height_greater_than_or_equal_to: "висота мусить бути більше або дорівнювати %{length} пікселям"
|
14
|
+
dimension_width_less_than_or_equal_to: "ширина мусить бути менше або дорівнювати %{length} пікселям"
|
15
|
+
dimension_height_less_than_or_equal_to: "висота мусить бути менше або дорівнювати %{length} пікселям"
|
16
|
+
dimension_width_equal_to: "ширина мусить дорівнювати %{length} пікселям"
|
17
|
+
dimension_height_equal_to: "висота мусить дорівнювати %{length} пікселям"
|
18
|
+
aspect_ratio_not_square: "мусить бути квадратне зображення"
|
19
|
+
aspect_ratio_not_portrait: "мусить бути портретне зображення"
|
20
|
+
aspect_ratio_not_landscape: "мусить бути пейзажне зображення"
|
21
|
+
aspect_ratio_is_not: "мусить мати співвідношення сторін %{aspect_ratio}"
|
22
|
+
aspect_ratio_unknown: "має невідоме співвідношення сторін"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
vi:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid: "tệp không hợp lệ"
|
5
|
+
file_size_out_of_range: "kích thước %{file_size} vượt giới hạn"
|
6
|
+
limit_out_of_range: "tổng số tệp vượt giới hạn"
|
7
|
+
image_metadata_missing: "không phải là ảnh"
|
8
|
+
dimension_min_inclusion: "phải lớn hơn hoặc bằng %{width} x %{height} pixel"
|
9
|
+
dimension_max_inclusion: "phải nhỏ hơn hoặc bằng %{width} x %{height} pixel"
|
10
|
+
dimension_width_inclusion: "chiều rộng không nằm trong %{min} và %{max} pixel"
|
11
|
+
dimension_height_inclusion: "chiều cao không nằm trong %{min} và %{max} pixel"
|
12
|
+
dimension_width_greater_than_or_equal_to: "chiều rộng phải lớn hơn hoặc bằng %{length} pixel"
|
13
|
+
dimension_height_greater_than_or_equal_to: "chiều cao phải lớn hơn hoặc bằng %{length} pixel"
|
14
|
+
dimension_width_less_than_or_equal_to: "chiều rộng phải nhỏ hơn hoặc bằng %{length} pixel"
|
15
|
+
dimension_height_less_than_or_equal_to: "chiều cao phải nhỏ hơn hoặc bằng %{length} pixel"
|
16
|
+
dimension_width_equal_to: "chiều rộng phải bằng %{length} pixel"
|
17
|
+
dimension_height_equal_to: "chiều cao phải bằng %{length} pixel"
|
18
|
+
aspect_ratio_not_square: "phải là ảnh hình vuông"
|
19
|
+
aspect_ratio_not_portrait: "phải là ảnh đứng"
|
20
|
+
aspect_ratio_not_landscape: "phải là ảnh ngang"
|
21
|
+
aspect_ratio_is_not: "phải có tỉ lệ ảnh %{aspect_ratio}"
|
22
|
+
aspect_ratio_unknown: "tỉ lệ ảnh không xác định"
|
@@ -18,7 +18,7 @@ module ActiveStorageValidations
|
|
18
18
|
raise ArgumentError, 'You must pass "aspect_ratio: :OPTION" option to the validator'
|
19
19
|
end
|
20
20
|
|
21
|
-
if Rails
|
21
|
+
if Rails.gem_version >= Gem::Version.new('6.0.0')
|
22
22
|
def validate_each(record, attribute, _value)
|
23
23
|
return true unless record.send(attribute).attached?
|
24
24
|
|
@@ -5,7 +5,10 @@ module ActiveStorageValidations
|
|
5
5
|
def validate_each(record, attribute, _value)
|
6
6
|
return if record.send(attribute).attached?
|
7
7
|
|
8
|
-
|
8
|
+
errors_options = {}
|
9
|
+
errors_options[:message] = options[:message] if options[:message].present?
|
10
|
+
|
11
|
+
record.errors.add(attribute, :blank, **errors_options)
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -14,14 +14,20 @@ module ActiveStorageValidations
|
|
14
14
|
next if is_valid?(file)
|
15
15
|
|
16
16
|
errors_options[:content_type] = content_type(file)
|
17
|
-
record.errors.add(attribute, :content_type_invalid, errors_options)
|
17
|
+
record.errors.add(attribute, :content_type_invalid, **errors_options)
|
18
18
|
break
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
def types
|
23
|
-
|
24
|
-
|
23
|
+
return @types if defined? @types
|
24
|
+
|
25
|
+
@types = (Array.wrap(options[:with]) + Array.wrap(options[:in])).compact.map do |type|
|
26
|
+
if type.is_a?(Regexp)
|
27
|
+
type
|
28
|
+
else
|
29
|
+
Marcel::MimeType.for(declared_type: type.to_s, extension: type.to_s)
|
30
|
+
end
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
@@ -36,10 +42,9 @@ module ActiveStorageValidations
|
|
36
42
|
end
|
37
43
|
|
38
44
|
def is_valid?(file)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
content_type(file).in?(types)
|
45
|
+
file_type = content_type(file)
|
46
|
+
types.any? do |type|
|
47
|
+
type == file_type || (type.is_a?(Regexp) && type.match?(file_type.to_s))
|
43
48
|
end
|
44
49
|
end
|
45
50
|
end
|
@@ -34,7 +34,7 @@ module ActiveStorageValidations
|
|
34
34
|
end
|
35
35
|
|
36
36
|
|
37
|
-
if Rails
|
37
|
+
if Rails.gem_version >= Gem::Version.new('6.0.0')
|
38
38
|
def validate_each(record, attribute, _value)
|
39
39
|
return true unless record.send(attribute).attached?
|
40
40
|
|
@@ -52,7 +52,7 @@ module ActiveStorageValidations
|
|
52
52
|
# Rails 5
|
53
53
|
def validate_each(record, attribute, _value)
|
54
54
|
return true unless record.send(attribute).attached?
|
55
|
-
|
55
|
+
|
56
56
|
files = Array.wrap(record.send(attribute))
|
57
57
|
files.each do |file|
|
58
58
|
# Analyze file first if not analyzed to get all required metadata.
|
@@ -110,7 +110,7 @@ module ActiveStorageValidations
|
|
110
110
|
else
|
111
111
|
if file_metadata[length] != options[length]
|
112
112
|
add_error(record, attribute, options[:message].presence || :"dimension_#{length}_equal_to", length: options[length])
|
113
|
-
return false
|
113
|
+
return false
|
114
114
|
end
|
115
115
|
end
|
116
116
|
end
|
@@ -119,11 +119,11 @@ module ActiveStorageValidations
|
|
119
119
|
true # valid file
|
120
120
|
end
|
121
121
|
|
122
|
-
def add_error(record, attribute, type,
|
122
|
+
def add_error(record, attribute, type, **attrs)
|
123
123
|
key = options[:message].presence || type
|
124
124
|
return if record.errors.added?(attribute, key)
|
125
|
-
record.errors.add(attribute, key,
|
126
|
-
end
|
125
|
+
record.errors.add(attribute, key, **attrs)
|
126
|
+
end
|
127
127
|
|
128
128
|
end
|
129
129
|
end
|
@@ -17,7 +17,7 @@ module ActiveStorageValidations
|
|
17
17
|
errors_options = { min: options[:min], max: options[:max] }
|
18
18
|
|
19
19
|
return true if files_count_valid?(files.count)
|
20
|
-
record.errors.add(attribute, options[:message].presence || :limit_out_of_range, errors_options)
|
20
|
+
record.errors.add(attribute, options[:message].presence || :limit_out_of_range, **errors_options)
|
21
21
|
end
|
22
22
|
|
23
23
|
def files_count_valid?(count)
|
@@ -16,9 +16,8 @@ module ActiveStorageValidations
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def matches?(subject)
|
19
|
-
@subject = subject.is_a?(Class) ? subject : subject
|
20
|
-
|
21
|
-
invalid_when_not_attached && valid_when_attached
|
19
|
+
@subject = subject.is_a?(Class) ? subject.new : subject
|
20
|
+
responds_to_methods && valid_when_attached && invalid_when_not_attached
|
22
21
|
end
|
23
22
|
|
24
23
|
def failure_message
|
@@ -31,17 +30,25 @@ module ActiveStorageValidations
|
|
31
30
|
|
32
31
|
private
|
33
32
|
|
33
|
+
def responds_to_methods
|
34
|
+
@subject.respond_to?(@attribute_name) &&
|
35
|
+
@subject.public_send(@attribute_name).respond_to?(:attach) &&
|
36
|
+
@subject.public_send(@attribute_name).respond_to?(:detach)
|
37
|
+
end
|
38
|
+
|
34
39
|
def valid_when_attached
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
instance.errors.details[@attribute_name].exclude?(error: :blank)
|
40
|
+
@subject.public_send(@attribute_name).attach(attachable) unless @subject.public_send(@attribute_name).attached?
|
41
|
+
@subject.validate
|
42
|
+
@subject.errors.details[@attribute_name].exclude?(error: :blank)
|
39
43
|
end
|
40
44
|
|
41
45
|
def invalid_when_not_attached
|
42
|
-
|
43
|
-
|
44
|
-
|
46
|
+
@subject.public_send(@attribute_name).detach
|
47
|
+
# Unset the direct relation since `detach` on an unpersisted record does not set `attached?` to false.
|
48
|
+
@subject.public_send("#{@attribute_name}=", nil)
|
49
|
+
|
50
|
+
@subject.validate
|
51
|
+
@subject.errors.details[@attribute_name].include?(error: :blank)
|
45
52
|
end
|
46
53
|
|
47
54
|
def attachable
|
@@ -29,7 +29,7 @@ module ActiveStorageValidations
|
|
29
29
|
|
30
30
|
def matches?(subject)
|
31
31
|
@subject = subject.is_a?(Class) ? subject.new : subject
|
32
|
-
allowed_types_allowed? && rejected_types_rejected?
|
32
|
+
responds_to_methods && allowed_types_allowed? && rejected_types_rejected?
|
33
33
|
end
|
34
34
|
|
35
35
|
def failure_message
|
@@ -46,12 +46,18 @@ module ActiveStorageValidations
|
|
46
46
|
|
47
47
|
protected
|
48
48
|
|
49
|
+
def responds_to_methods
|
50
|
+
@subject.respond_to?(@attribute_name) &&
|
51
|
+
@subject.public_send(@attribute_name).respond_to?(:attach) &&
|
52
|
+
@subject.public_send(@attribute_name).respond_to?(:detach)
|
53
|
+
end
|
54
|
+
|
49
55
|
def allowed_types
|
50
56
|
@allowed_types || []
|
51
57
|
end
|
52
58
|
|
53
59
|
def rejected_types
|
54
|
-
@rejected_types || (
|
60
|
+
@rejected_types || (Marcel::TYPES.keys - allowed_types)
|
55
61
|
end
|
56
62
|
|
57
63
|
def allowed_types_allowed?
|
@@ -10,6 +10,7 @@ module ActiveStorageValidations
|
|
10
10
|
def initialize(attribute_name)
|
11
11
|
@attribute_name = attribute_name
|
12
12
|
@width_min = @width_max = @height_min = @height_max = nil
|
13
|
+
@custom_message = nil
|
13
14
|
end
|
14
15
|
|
15
16
|
def description
|
@@ -26,6 +27,11 @@ module ActiveStorageValidations
|
|
26
27
|
self
|
27
28
|
end
|
28
29
|
|
30
|
+
def with_message(message)
|
31
|
+
@custom_message = message
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
29
35
|
def width(width)
|
30
36
|
@width_min = @width_max = width
|
31
37
|
self
|
@@ -58,7 +64,8 @@ module ActiveStorageValidations
|
|
58
64
|
|
59
65
|
def matches?(subject)
|
60
66
|
@subject = subject.is_a?(Class) ? subject.new : subject
|
61
|
-
|
67
|
+
responds_to_methods &&
|
68
|
+
width_smaller_than_min? && width_larger_than_min? && width_smaller_than_max? && width_larger_than_max? && width_equals? &&
|
62
69
|
height_smaller_than_min? && height_larger_than_min? && height_smaller_than_max? && height_larger_than_max? && height_equals?
|
63
70
|
end
|
64
71
|
|
@@ -72,6 +79,12 @@ module ActiveStorageValidations
|
|
72
79
|
|
73
80
|
protected
|
74
81
|
|
82
|
+
def responds_to_methods
|
83
|
+
@subject.respond_to?(@attribute_name) &&
|
84
|
+
@subject.public_send(@attribute_name).respond_to?(:attach) &&
|
85
|
+
@subject.public_send(@attribute_name).respond_to?(:detach)
|
86
|
+
end
|
87
|
+
|
75
88
|
def valid_width
|
76
89
|
((@width_min || 0) + (@width_max || 2000)) / 2
|
77
90
|
end
|
@@ -126,7 +139,8 @@ module ActiveStorageValidations
|
|
126
139
|
attachment = @subject.public_send(@attribute_name)
|
127
140
|
Matchers.mock_metadata(attachment, width, height) do
|
128
141
|
@subject.validate
|
129
|
-
@
|
142
|
+
exclude_error_message = @custom_message || "dimension_#{check}"
|
143
|
+
@subject.errors.details[@attribute_name].all? { |error| error[:error].to_s.exclude?(exclude_error_message) }
|
130
144
|
end
|
131
145
|
end
|
132
146
|
|
@@ -45,7 +45,7 @@ module ActiveStorageValidations
|
|
45
45
|
|
46
46
|
def matches?(subject)
|
47
47
|
@subject = subject.is_a?(Class) ? subject.new : subject
|
48
|
-
lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
|
48
|
+
responds_to_methods && lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
|
49
49
|
end
|
50
50
|
|
51
51
|
def failure_message
|
@@ -58,6 +58,12 @@ module ActiveStorageValidations
|
|
58
58
|
|
59
59
|
protected
|
60
60
|
|
61
|
+
def responds_to_methods
|
62
|
+
@subject.respond_to?(@attribute_name) &&
|
63
|
+
@subject.public_send(@attribute_name).respond_to?(:attach) &&
|
64
|
+
@subject.public_send(@attribute_name).respond_to?(:detach)
|
65
|
+
end
|
66
|
+
|
61
67
|
def lower_than_low?
|
62
68
|
@low.nil? || !passes_validation_with_size(@low - 1)
|
63
69
|
end
|
@@ -22,7 +22,7 @@ module ActiveStorageValidations
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.mock_metadata(attachment, width, height)
|
25
|
-
if Rails
|
25
|
+
if Rails.gem_version >= Gem::Version.new('6.0.0')
|
26
26
|
# Mock the Metadata class for rails 6
|
27
27
|
mock = OpenStruct.new(metadata: { width: width, height: height })
|
28
28
|
stub_method(ActiveStorageValidations::Metadata, :new, mock) do
|
@@ -21,7 +21,16 @@ module ActiveStorageValidations
|
|
21
21
|
def read_image
|
22
22
|
is_string = file.is_a?(String)
|
23
23
|
if is_string || file.is_a?(ActiveStorage::Blob)
|
24
|
-
blob =
|
24
|
+
blob =
|
25
|
+
if is_string
|
26
|
+
if Rails.gem_version < Gem::Version.new('6.1.0')
|
27
|
+
ActiveStorage::Blob.find_signed(file)
|
28
|
+
else
|
29
|
+
ActiveStorage::Blob.find_signed!(file)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
file
|
33
|
+
end
|
25
34
|
|
26
35
|
tempfile = Tempfile.new(["ActiveStorage-#{blob.id}-", blob.filename.extension_with_delimiter])
|
27
36
|
tempfile.binmode
|
@@ -25,7 +25,10 @@ module ActiveStorageValidations
|
|
25
25
|
next if content_size_valid?(file.blob.byte_size)
|
26
26
|
|
27
27
|
errors_options[:file_size] = number_to_human_size(file.blob.byte_size)
|
28
|
-
|
28
|
+
errors_options[:min_size] = number_to_human_size(min_size)
|
29
|
+
errors_options[:max_size] = number_to_human_size(max_size)
|
30
|
+
|
31
|
+
record.errors.add(attribute, :file_size_out_of_range, **errors_options)
|
29
32
|
break
|
30
33
|
end
|
31
34
|
end
|
@@ -43,5 +46,13 @@ module ActiveStorageValidations
|
|
43
46
|
file_size >= options[:greater_than_or_equal_to]
|
44
47
|
end
|
45
48
|
end
|
49
|
+
|
50
|
+
def min_size
|
51
|
+
options[:between]&.min || options[:greater_than] || options[:greater_than_or_equal_to]
|
52
|
+
end
|
53
|
+
|
54
|
+
def max_size
|
55
|
+
options[:between]&.max || options[:less_than] || options[:less_than_or_equal_to]
|
56
|
+
end
|
46
57
|
end
|
47
58
|
end
|
File without changes
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_storage_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Kasyanchuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activejob
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -25,35 +25,77 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 5.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
type: :
|
33
|
+
version: 5.2.0
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 5.2.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: activestorage
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 5.2.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 5.2.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 5.2.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 5.2.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: combustion
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.3'
|
48
76
|
type: :development
|
49
77
|
prerelease: false
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mini_magick
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
51
86
|
requirements:
|
52
87
|
- - ">="
|
53
88
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
89
|
+
version: 4.9.5
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 4.9.5
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
98
|
+
name: pry
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
58
100
|
requirements:
|
59
101
|
- - ">="
|
@@ -67,7 +109,7 @@ dependencies:
|
|
67
109
|
- !ruby/object:Gem::Version
|
68
110
|
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
112
|
+
name: rubocop
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
72
114
|
requirements:
|
73
115
|
- - ">="
|
@@ -81,7 +123,7 @@ dependencies:
|
|
81
123
|
- !ruby/object:Gem::Version
|
82
124
|
version: '0'
|
83
125
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
126
|
+
name: sqlite3
|
85
127
|
requirement: !ruby/object:Gem::Requirement
|
86
128
|
requirements:
|
87
129
|
- - ">="
|
@@ -106,11 +148,17 @@ files:
|
|
106
148
|
- Rakefile
|
107
149
|
- config/locales/de.yml
|
108
150
|
- config/locales/en.yml
|
151
|
+
- config/locales/es.yml
|
109
152
|
- config/locales/fr.yml
|
153
|
+
- config/locales/it.yml
|
110
154
|
- config/locales/ja.yml
|
155
|
+
- config/locales/nl.yml
|
156
|
+
- config/locales/pl.yml
|
111
157
|
- config/locales/pt-BR.yml
|
112
158
|
- config/locales/ru.yml
|
159
|
+
- config/locales/tr.yml
|
113
160
|
- config/locales/uk.yml
|
161
|
+
- config/locales/vi.yml
|
114
162
|
- lib/active_storage_validations.rb
|
115
163
|
- lib/active_storage_validations/aspect_ratio_validator.rb
|
116
164
|
- lib/active_storage_validations/attached_validator.rb
|
@@ -147,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
195
|
- !ruby/object:Gem::Version
|
148
196
|
version: '0'
|
149
197
|
requirements: []
|
150
|
-
rubygems_version: 3.
|
198
|
+
rubygems_version: 3.1.4
|
151
199
|
signing_key:
|
152
200
|
specification_version: 4
|
153
201
|
summary: Validations for Active Storage
|