active_storage_validations 2.0.2 → 2.0.3
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 +9 -61
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +1 -0
- data/config/locales/en-GB.yml +54 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/fr.yml +1 -0
- data/config/locales/it.yml +2 -1
- data/config/locales/ja.yml +1 -0
- data/config/locales/nl.yml +1 -0
- data/config/locales/pl.yml +1 -0
- data/config/locales/pt-BR.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/config/locales/sv.yml +1 -0
- data/config/locales/tr.yml +1 -0
- data/config/locales/uk.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +1 -0
- data/lib/active_storage_validations/analyzer/audio_analyzer.rb +2 -2
- data/lib/active_storage_validations/analyzer/content_type_analyzer.rb +5 -5
- data/lib/active_storage_validations/analyzer/image_analyzer/image_magick.rb +0 -1
- data/lib/active_storage_validations/analyzer/image_analyzer/vips.rb +0 -1
- data/lib/active_storage_validations/analyzer/video_analyzer.rb +4 -4
- data/lib/active_storage_validations/analyzer.rb +24 -23
- data/lib/active_storage_validations/aspect_ratio_validator.rb +19 -16
- data/lib/active_storage_validations/attached_validator.rb +3 -3
- data/lib/active_storage_validations/base_comparison_validator.rb +6 -6
- data/lib/active_storage_validations/content_type_validator.rb +34 -21
- data/lib/active_storage_validations/dimension_validator.rb +158 -82
- data/lib/active_storage_validations/duration_validator.rb +28 -14
- data/lib/active_storage_validations/extensors/asv_blob_metadatable.rb +15 -8
- data/lib/active_storage_validations/extensors/asv_marcelable.rb +1 -1
- data/lib/active_storage_validations/limit_validator.rb +27 -19
- data/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +12 -12
- data/lib/active_storage_validations/matchers/attached_validator_matcher.rb +6 -6
- data/lib/active_storage_validations/matchers/base_comparison_validator_matcher.rb +7 -7
- data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +15 -13
- data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +8 -8
- data/lib/active_storage_validations/matchers/duration_validator_matcher.rb +2 -2
- data/lib/active_storage_validations/matchers/limit_validator_matcher.rb +8 -8
- data/lib/active_storage_validations/matchers/processable_file_validator_matcher.rb +7 -7
- data/lib/active_storage_validations/matchers/shared/asv_active_storageable.rb +1 -1
- data/lib/active_storage_validations/matchers/shared/asv_allow_blankable.rb +1 -1
- data/lib/active_storage_validations/matchers/shared/asv_attachable.rb +9 -9
- data/lib/active_storage_validations/matchers/shared/asv_contextable.rb +11 -3
- data/lib/active_storage_validations/matchers/shared/asv_messageable.rb +1 -1
- data/lib/active_storage_validations/matchers/shared/asv_rspecable.rb +2 -2
- data/lib/active_storage_validations/matchers/shared/asv_validatable.rb +2 -2
- data/lib/active_storage_validations/matchers/size_validator_matcher.rb +2 -2
- data/lib/active_storage_validations/matchers/total_size_validator_matcher.rb +3 -3
- data/lib/active_storage_validations/matchers.rb +10 -10
- data/lib/active_storage_validations/processable_file_validator.rb +37 -37
- data/lib/active_storage_validations/railtie.rb +2 -2
- data/lib/active_storage_validations/shared/asv_attachable.rb +60 -28
- data/lib/active_storage_validations/shared/asv_errorable.rb +1 -1
- data/lib/active_storage_validations/shared/asv_symbolizable.rb +1 -1
- data/lib/active_storage_validations/size_validator.rb +1 -1
- data/lib/active_storage_validations/total_size_validator.rb +2 -2
- data/lib/active_storage_validations/version.rb +1 -1
- data/lib/active_storage_validations.rb +22 -22
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ba7e03a6367634ed5ece53bda87d82c76b179c75e2c9b37e4055d8f47f9ab98
|
4
|
+
data.tar.gz: 7225e4937cab59e3209d082d9650c1077342eae7dcae46ddee0c25a9a5e93e56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9464b889ae0f8ab4167bcc612926e44c52d3541de6092fa0c82baf57a2f9edb4f541780145443966fa168c8f3f819456b000fac4a8770c1e923219a7394918da
|
7
|
+
data.tar.gz: 4dea3b65668a16cac757d85f4e8d8f31e98c5089bbcf5747a5f192083fb12e2b57d611091eb2e2fb468aff27c590cdad1232566f24b75415784c7fe28434013f
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ $ bundle
|
|
53
53
|
|
54
54
|
### Error messages (I18n)
|
55
55
|
|
56
|
-
Once you have installed the gem,
|
56
|
+
Once you have installed the gem, I18n error messages will be added automatically to your app. See [Internationalization (I18n)](#internationalization-i18n) section for more details.
|
57
57
|
|
58
58
|
### Using image metadata validators
|
59
59
|
|
@@ -71,6 +71,8 @@ Plus, you have to be sure to have the corresponding command-line tool installed
|
|
71
71
|
|
72
72
|
To use the video and audio metadata validators (`dimension`, `aspect_ratio`, `processable_file` and `duration`), you will not need to add any gems. However you will need to have the `ffmpeg` command-line tool installed on your system (once again, be sure to have it installed both on your local and in your CI / production environments).
|
73
73
|
|
74
|
+
If you want some inspiration about how to add `imagemagick`, `libvips` or `ffmpeg` to your docker image, you can check how we do it for the gem CI (https://github.com/igorkasyanchuk/active_storage_validations/blob/master/.github/workflows/main.yml)
|
75
|
+
|
74
76
|
### Using content type spoofing protection validator option
|
75
77
|
|
76
78
|
To use the `spoofing_protection` option with the `content_type` validator, you only need to have the UNIX `file` command on your system.
|
@@ -248,7 +250,7 @@ If you choose to use a content_type 'shorthand' (like `png`), note that it will
|
|
248
250
|
Marcel::MimeType.extend "application/ino", extensions: %w(ino), parents: "text/plain" # Registering arduino INO files
|
249
251
|
```
|
250
252
|
|
251
|
-
Be sure to at least include one the
|
253
|
+
Be sure to at least include one the `extensions`, `parents` or `magic` option, otherwise the content type will not be registered.
|
252
254
|
|
253
255
|
#### Content type spoofing protection
|
254
256
|
|
@@ -656,65 +658,11 @@ But this major version bump also comes with some breaking changes. Below are the
|
|
656
658
|
|
657
659
|
## Internationalization (I18n)
|
658
660
|
|
659
|
-
Active Storage Validations uses I18n for error messages.
|
661
|
+
Active Storage Validations uses I18n for error messages. The error messages are automatically loaded in your Rails app if your language translations are present in the gem.
|
660
662
|
|
661
|
-
|
662
|
-
en:
|
663
|
-
errors:
|
664
|
-
messages:
|
665
|
-
content_type_invalid:
|
666
|
-
one: "has an invalid content type (authorized content type is %{authorized_human_content_types})"
|
667
|
-
other: "has an invalid content type (authorized content types are %{authorized_human_content_types})"
|
668
|
-
content_type_spoofed:
|
669
|
-
one: "has a content type that is not equivalent to the one that is detected through its content (authorized content type is %{authorized_human_content_types})"
|
670
|
-
other: "has a content type that is not equivalent to the one that is detected through its content (authorized content types are %{authorized_human_content_types})"
|
671
|
-
file_size_not_less_than: "file size must be less than %{max} (current size is %{file_size})"
|
672
|
-
file_size_not_less_than_or_equal_to: "file size must be less than or equal to %{max} (current size is %{file_size})"
|
673
|
-
file_size_not_greater_than: "file size must be greater than %{min} (current size is %{file_size})"
|
674
|
-
file_size_not_greater_than_or_equal_to: "file size must be greater than or equal to %{min} (current size is %{file_size})"
|
675
|
-
file_size_not_between: "file size must be between %{min} and %{max} (current size is %{file_size})"
|
676
|
-
total_file_size_not_less_than: "total file size must be less than %{max} (current size is %{total_file_size})"
|
677
|
-
total_file_size_not_less_than_or_equal_to: "total file size must be less than or equal to %{max} (current size is %{total_file_size})"
|
678
|
-
total_file_size_not_greater_than: "total file size must be greater than %{min} (current size is %{total_file_size})"
|
679
|
-
total_file_size_not_greater_than_or_equal_to: "total file size must be greater than or equal to %{min} (current size is %{total_file_size})"
|
680
|
-
total_file_size_not_between: "total file size must be between %{min} and %{max} (current size is %{total_file_size})"
|
681
|
-
duration_not_less_than: "duration must be less than %{max} (current duration is %{duration})"
|
682
|
-
duration_not_less_than_or_equal_to: "duration must be less than or equal to %{max} (current duration is %{duration})"
|
683
|
-
duration_not_greater_than: "duration must be greater than %{min} (current duration is %{duration})"
|
684
|
-
duration_not_greater_than_or_equal_to: "duration must be greater than or equal to %{min} (current duration is %{duration})"
|
685
|
-
duration_not_between: "duration must be between %{min} and %{max} (current duration is %{duration})"
|
686
|
-
limit_out_of_range:
|
687
|
-
zero: "no files attached (must have between %{min} and %{max} files)"
|
688
|
-
one: "only 1 file attached (must have between %{min} and %{max} files)"
|
689
|
-
other: "total number of files must be between %{min} and %{max} files (there are %{count} files attached)"
|
690
|
-
limit_min_not_reached:
|
691
|
-
zero: "no files attached (must have at least %{min} files)"
|
692
|
-
one: "only 1 file attached (must have at least %{min} files)"
|
693
|
-
other: "%{count} files attached (must have at least %{min} files)"
|
694
|
-
limit_max_exceeded:
|
695
|
-
zero: "no files attached (maximum is %{max} files)"
|
696
|
-
one: "too many files attached (maximum is %{max} files, got %{count})"
|
697
|
-
other: "too many files attached (maximum is %{max} files, got %{count})"
|
698
|
-
media_metadata_missing: "is not a valid media file"
|
699
|
-
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixel"
|
700
|
-
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixel"
|
701
|
-
dimension_width_not_included_in: "width is not included between %{min} and %{max} pixel"
|
702
|
-
dimension_height_not_included_in: "height is not included between %{min} and %{max} pixel"
|
703
|
-
dimension_width_not_greater_than_or_equal_to: "width must be greater than or equal to %{length} pixel"
|
704
|
-
dimension_height_not_greater_than_or_equal_to: "height must be greater than or equal to %{length} pixel"
|
705
|
-
dimension_width_not_less_than_or_equal_to: "width must be less than or equal to %{length} pixel"
|
706
|
-
dimension_height_not_less_than_or_equal_to: "height must be less than or equal to %{length} pixel"
|
707
|
-
dimension_width_not_equal_to: "width must be equal to %{length} pixel"
|
708
|
-
dimension_height_not_equal_to: "height must be equal to %{length} pixel"
|
709
|
-
aspect_ratio_not_square: "must be square (current file is %{width}x%{height}px)"
|
710
|
-
aspect_ratio_not_portrait: "must be portrait (current file is %{width}x%{height}px)"
|
711
|
-
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
|
712
|
-
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
|
713
|
-
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
|
714
|
-
file_not_processable: "is not identified as a valid media file"
|
715
|
-
```
|
663
|
+
Translation files are available [here](https://github.com/igorkasyanchuk/active_storage_validations/tree/master/config/locales). We currently have translations for `da`, `de`, `en`, `en-GB`, `es`, `fr`, `it`, `ja`, `nl`, `pl`, `pt-BR`, `ru`, `sv`, `tr`, `uk`, `vi` and `zh-CN`. Feel free to drop a PR to add your language ✌️.
|
716
664
|
|
717
|
-
|
665
|
+
If you wish to customize the error messages, just copy, paste and update the translation files into your application locales.
|
718
666
|
|
719
667
|
## Test matchers
|
720
668
|
|
@@ -760,8 +708,8 @@ describe User do
|
|
760
708
|
|
761
709
|
# content_type:
|
762
710
|
# #allowing, #rejecting
|
763
|
-
it { is_expected.to validate_content_type_of(:avatar).allowing('image/png', 'image/gif') }
|
764
|
-
it { is_expected.to validate_content_type_of(:avatar).rejecting('text/plain', 'text/xml') }
|
711
|
+
it { is_expected.to validate_content_type_of(:avatar).allowing('image/png', 'image/gif') } # possible to use an Array or *splatted array
|
712
|
+
it { is_expected.to validate_content_type_of(:avatar).rejecting('text/plain', 'text/xml') } # possible to use an Array or *splatted array
|
765
713
|
|
766
714
|
# dimension:
|
767
715
|
# #width, #height, #width_min, #height_min, #width_max, #height_max, #width_between, #height_between
|
data/config/locales/da.yml
CHANGED
@@ -34,6 +34,7 @@ da:
|
|
34
34
|
zero: "ingen filer vedhæftet (maks. er %{max} filer)"
|
35
35
|
one: "for mange vedhæftede filer (maks. er %{max} filer, fik %{count})"
|
36
36
|
other: "for mange vedhæftede filer (maks. er %{max} filer, fik %{count})"
|
37
|
+
attachment_missing: "har ingen vedhæftet fil"
|
37
38
|
media_metadata_missing: "er ikke en gyldig mediefil"
|
38
39
|
dimension_min_not_included_in: "skal være større end eller lig med %{width} x %{height} pixel"
|
39
40
|
dimension_max_not_included_in: "skal være mindre end eller lig med %{width} x %{height} pixel"
|
data/config/locales/de.yml
CHANGED
@@ -34,6 +34,7 @@ de:
|
|
34
34
|
zero: "Keine Dateien angehängt (maximal %{max} Dateien)"
|
35
35
|
one: "zu viele angehängte Dateien (maximal %{max} Dateien, %{count})"
|
36
36
|
other: "Zu viele angehängte Dateien (maximal %{max} Dateien, %{count})"
|
37
|
+
attachment_missing: "hat keine angehängte Datei"
|
37
38
|
media_metadata_missing: "ist keine gültige Mediendatei"
|
38
39
|
dimension_min_not_included_in: "muss größer oder gleich %{width} x %{height} Pixel sein"
|
39
40
|
dimension_max_not_included_in: "muss kleiner oder gleich %{width} x %{height} Pixel sein"
|
@@ -0,0 +1,54 @@
|
|
1
|
+
en-GB:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
content_type_invalid:
|
5
|
+
one: "has an invalid content type (authorized content type is %{authorized_human_content_types})"
|
6
|
+
other: "has an invalid content type (authorized content types are %{authorized_human_content_types})"
|
7
|
+
content_type_spoofed:
|
8
|
+
one: "has a content type that is not equivalent to the one that is detected through its content (authorized content type is %{authorized_human_content_types})"
|
9
|
+
other: "has a content type that is not equivalent to the one that is detected through its content (authorized content types are %{authorized_human_content_types})"
|
10
|
+
file_size_not_less_than: "file size must be less than %{max} (current size is %{file_size})"
|
11
|
+
file_size_not_less_than_or_equal_to: "file size must be less than or equal to %{max} (current size is %{file_size})"
|
12
|
+
file_size_not_greater_than: "file size must be greater than %{min} (current size is %{file_size})"
|
13
|
+
file_size_not_greater_than_or_equal_to: "file size must be greater than or equal to %{min} (current size is %{file_size})"
|
14
|
+
file_size_not_between: "file size must be between %{min} and %{max} (current size is %{file_size})"
|
15
|
+
total_file_size_not_less_than: "total file size must be less than %{max} (current size is %{total_file_size})"
|
16
|
+
total_file_size_not_less_than_or_equal_to: "total file size must be less than or equal to %{max} (current size is %{total_file_size})"
|
17
|
+
total_file_size_not_greater_than: "total file size must be greater than %{min} (current size is %{total_file_size})"
|
18
|
+
total_file_size_not_greater_than_or_equal_to: "total file size must be greater than or equal to %{min} (current size is %{total_file_size})"
|
19
|
+
total_file_size_not_between: "total file size must be between %{min} and %{max} (current size is %{total_file_size})"
|
20
|
+
duration_not_less_than: "duration must be less than %{max} (current duration is %{duration})"
|
21
|
+
duration_not_less_than_or_equal_to: "duration must be less than or equal to %{max} (current duration is %{duration})"
|
22
|
+
duration_not_greater_than: "duration must be greater than %{min} (current duration is %{duration})"
|
23
|
+
duration_not_greater_than_or_equal_to: "duration must be greater than or equal to %{min} (current duration is %{duration})"
|
24
|
+
duration_not_between: "duration must be between %{min} and %{max} (current duration is %{duration})"
|
25
|
+
limit_out_of_range:
|
26
|
+
zero: "no files attached (must have between %{min} and %{max} files)"
|
27
|
+
one: "only 1 file attached (must have between %{min} and %{max} files)"
|
28
|
+
other: "total number of files must be between %{min} and %{max} files (there are %{count} files attached)"
|
29
|
+
limit_min_not_reached:
|
30
|
+
zero: "no files attached (must have at least %{min} files)"
|
31
|
+
one: "only 1 file attached (must have at least %{min} files)"
|
32
|
+
other: "%{count} files attached (must have at least %{min} files)"
|
33
|
+
limit_max_exceeded:
|
34
|
+
zero: "no files attached (maximum is %{max} files)"
|
35
|
+
one: "too many files attached (maximum is %{max} files, got %{count})"
|
36
|
+
other: "too many files attached (maximum is %{max} files, got %{count})"
|
37
|
+
attachment_missing: "is missing its attachment"
|
38
|
+
media_metadata_missing: "is not a valid media file"
|
39
|
+
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixel"
|
40
|
+
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixel"
|
41
|
+
dimension_width_not_included_in: "width is not included between %{min} and %{max} pixel"
|
42
|
+
dimension_height_not_included_in: "height is not included between %{min} and %{max} pixel"
|
43
|
+
dimension_width_not_greater_than_or_equal_to: "width must be greater than or equal to %{length} pixel"
|
44
|
+
dimension_height_not_greater_than_or_equal_to: "height must be greater than or equal to %{length} pixel"
|
45
|
+
dimension_width_not_less_than_or_equal_to: "width must be less than or equal to %{length} pixel"
|
46
|
+
dimension_height_not_less_than_or_equal_to: "height must be less than or equal to %{length} pixel"
|
47
|
+
dimension_width_not_equal_to: "width must be equal to %{length} pixel"
|
48
|
+
dimension_height_not_equal_to: "height must be equal to %{length} pixel"
|
49
|
+
aspect_ratio_not_square: "must be square (current file is %{width}x%{height}px)"
|
50
|
+
aspect_ratio_not_portrait: "must be portrait (current file is %{width}x%{height}px)"
|
51
|
+
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
|
52
|
+
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
|
53
|
+
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
|
54
|
+
file_not_processable: "is not identified as a valid media file"
|
data/config/locales/en.yml
CHANGED
@@ -34,6 +34,7 @@ en:
|
|
34
34
|
zero: "no files attached (maximum is %{max} files)"
|
35
35
|
one: "too many files attached (maximum is %{max} files, got %{count})"
|
36
36
|
other: "too many files attached (maximum is %{max} files, got %{count})"
|
37
|
+
attachment_missing: "is missing its attachment"
|
37
38
|
media_metadata_missing: "is not a valid media file"
|
38
39
|
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixel"
|
39
40
|
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixel"
|
data/config/locales/es.yml
CHANGED
@@ -34,6 +34,7 @@ es:
|
|
34
34
|
zero: "no hay archivos adjuntos (máximo es %{max} archivos)"
|
35
35
|
one: "demasiados archivos adjuntos (máximo es %{max} archivos, got %{count})"
|
36
36
|
other: "demasiados archivos adjuntos (máximo es %{max} archivos, got %{count})"
|
37
|
+
attachment_missing: "no tiene archivo adjunto"
|
37
38
|
media_metadata_missing: "no es un archivo multimedia válido"
|
38
39
|
dimension_min_not_included_in: "debe ser mayor o igual a %{width} x %{height} pixel"
|
39
40
|
dimension_max_not_included_in: "debe ser menor o igual a %{width} x %{height} pixel"
|
data/config/locales/fr.yml
CHANGED
@@ -34,6 +34,7 @@ fr:
|
|
34
34
|
zero: "pas de fichiers joints (le maximum autorisé est %{max} fichiers)"
|
35
35
|
one: "trop de fichiers joints (le maximum autorisé est %{max} fichiers, obtenu %{count})"
|
36
36
|
other: "trop de fichiers joints (le maximum autorisé est %{max} fichiers, obtenu %{count})"
|
37
|
+
attachment_missing: "n'a pas de fichier joint"
|
37
38
|
media_metadata_missing: "n'est pas un fichier média valide"
|
38
39
|
dimension_min_not_included_in: "doit être supérieur ou égal à %{width} x %{height} pixels"
|
39
40
|
dimension_max_not_included_in: "doit être inférieur ou égal à %{width} x %{height} pixels"
|
data/config/locales/it.yml
CHANGED
@@ -19,7 +19,7 @@ it:
|
|
19
19
|
total_file_size_not_between: "la dimensione totale dei file deve essere compresa tra %{min} e %{max} (la dimensione attuale è %{total_file_size})"
|
20
20
|
duration_not_less_than: "la durata deve essere inferiore a %{max} (la durata corrente è %{duration})"
|
21
21
|
duration_not_less_than_or_equal_to: "la durata deve essere inferiore o uguale a %{max} (la durata corrente è %{duration})"
|
22
|
-
|
22
|
+
duration_not_greater_than: "la durata deve essere superiore a %{min} (la durata corrente è %{duration})"
|
23
23
|
duration_not_greater_than_or_equal_to: "la durata deve essere maggiore o uguale a %{min} (la durata corrente è %{duration})"
|
24
24
|
duration_not_between: "la durata deve essere compresa tra %{min} e %{max} (la durata corrente è %{duration})"
|
25
25
|
limit_out_of_range:
|
@@ -34,6 +34,7 @@ it:
|
|
34
34
|
zero: "nessun file allegato (massimo è %{max} file)"
|
35
35
|
one: "troppi file allegati (massimo è %{max} file, ottenuto %{count})"
|
36
36
|
other: "troppi file allegati (massimo è %{max} file, ottenuto %{count})"
|
37
|
+
attachment_missing: "non ha un file allegato"
|
37
38
|
media_metadata_missing: "non è un file multimediale valido"
|
38
39
|
dimension_min_not_included_in: "deve essere maggiore o uguale a %{width} x %{height} pixel"
|
39
40
|
dimension_max_not_included_in: "deve essere minore o uguale a %{width} x %{height} pixel"
|
data/config/locales/ja.yml
CHANGED
@@ -34,6 +34,7 @@ ja:
|
|
34
34
|
zero: "添付されたファイルはありません(最大は%{max}ファイル)"
|
35
35
|
one: "添付されているファイルが多すぎます(最大は%{max}ファイル、%{count})"
|
36
36
|
other: "添付されているファイルが多すぎます(最大は%{max}ファイル、%{count})"
|
37
|
+
attachment_missing: "添付ファイルがありません"
|
37
38
|
media_metadata_missing: "有効なメディアファイルではありません"
|
38
39
|
dimension_min_not_included_in: "は %{width} x %{height} ピクセル以上の大きさにしてください"
|
39
40
|
dimension_max_not_included_in: "は %{width} x %{height} ピクセル以下の大きさにしてください"
|
data/config/locales/nl.yml
CHANGED
@@ -34,6 +34,7 @@ nl:
|
|
34
34
|
zero: "geen bestanden bijgevoegd (maximaal is %{max} bestanden)"
|
35
35
|
one: "te veel bijgevoegde bestanden (maximaal is %{max} bestanden, kreeg %{count})"
|
36
36
|
other: "te veel bijgevoegde bestanden (maximum is %{max} bestanden, kreeg %{count})"
|
37
|
+
attachment_missing: "heeft geen bijgevoegd bestand"
|
37
38
|
media_metadata_missing: "is geen geldig mediabestand"
|
38
39
|
dimension_min_not_included_in: "moet groter of gelijk zijn aan %{width} x %{height} pixels"
|
39
40
|
dimension_max_not_included_in: "moet kleiner of gelijk zijn aan %{width} x %{height} pixels"
|
data/config/locales/pl.yml
CHANGED
@@ -34,6 +34,7 @@ pl:
|
|
34
34
|
zero: "brak dołączonych plików (maksymalnie jest to %{max} pliki)"
|
35
35
|
one: "zbyt wiele dołączonych plików (maksymalnie jest to %{max} pliki, otrzymano %{count})"
|
36
36
|
other: "zbyt wiele dołączonych plików (maksymalnie jest to %{max} pliki, otrzymano %{count})"
|
37
|
+
attachment_missing: "nie ma załączonego pliku"
|
37
38
|
media_metadata_missing: "nie jest prawidłowym plikiem multimedialnym"
|
38
39
|
dimension_min_not_included_in: "musi być równe lub większe od %{width} x %{height} pixeli"
|
39
40
|
dimension_max_not_included_in: "musi być równe lub mniejsze od %{width} x %{height} pixeli"
|
data/config/locales/pt-BR.yml
CHANGED
@@ -34,6 +34,7 @@ pt-BR:
|
|
34
34
|
zero: "sem arquivos anexados (o máximo é %{max})"
|
35
35
|
one: "muitos arquivos anexados (o máximo é %{max}, obteve %{count})"
|
36
36
|
other: "muitos arquivos anexados (o máximo é %{max}, obteve %{count})"
|
37
|
+
attachment_missing: "não tem nenhum arquivo anexado"
|
37
38
|
media_metadata_missing: "não é um arquivo de mídia válido"
|
38
39
|
dimension_min_not_included_in: "deve ser maior ou igual a %{width} x %{height} pixels"
|
39
40
|
dimension_max_not_included_in: "deve ser menor ou igual a %{width} x %{height} pixels"
|
data/config/locales/ru.yml
CHANGED
@@ -34,6 +34,7 @@ ru:
|
|
34
34
|
zero: "никаких файлов не прилагается (максимум составляет %{max} файлов)"
|
35
35
|
one: "слишком много файлов прикреплено (максимум составляет %{max} файлов, получил %{count})"
|
36
36
|
other: "слишком много файлов прикреплено (максимум составляет %{max} файлов, получил %{count})"
|
37
|
+
attachment_missing: "не имеет прикрепленного файла"
|
37
38
|
media_metadata_missing: "не является действительным медиафайлом"
|
38
39
|
dimension_min_not_included_in: "должен быть больше или равно %{width} x %{height} пикселям"
|
39
40
|
dimension_max_not_included_in: "должно быть меньше или равно %{width} x %{height} пикселям"
|
data/config/locales/sv.yml
CHANGED
@@ -34,6 +34,7 @@ sv:
|
|
34
34
|
zero: "inga filer bifogade (maximalt är %{max} filer)"
|
35
35
|
one: "för många filer bifogade (maximalt är %{max} -filer, fick %{count})"
|
36
36
|
other: "för många filer bifogade (maximalt är %{max} -filer, fick %{count})"
|
37
|
+
attachment_missing: "har ingen bifogad fil"
|
37
38
|
media_metadata_missing: "är inte en giltig mediefil"
|
38
39
|
dimension_min_not_included_in: "måste minst vara %{width} x %{height} pixlar"
|
39
40
|
dimension_max_not_included_in: "måste vara mindre eller lika med %{width} x %{height} pixlar"
|
data/config/locales/tr.yml
CHANGED
@@ -34,6 +34,7 @@ tr:
|
|
34
34
|
zero: "dosya eklenmedi (maksimum %{max} dosyaları)"
|
35
35
|
one: "çok fazla dosya eklendi (maksimum %{max} dosyaları, %{count})"
|
36
36
|
other: "çok fazla dosya eklendi (maksimum %{max} dosyaları, %{count} var)"
|
37
|
+
attachment_missing: "ekli dosya yok"
|
37
38
|
media_metadata_missing: "geçerli bir medya dosyası değil"
|
38
39
|
dimension_min_not_included_in: "%{width} x %{height} piksele eşit ya da büyük olmalı"
|
39
40
|
dimension_max_not_included_in: "%{width} x %{height} piksele eşit ya da küçük olmalı"
|
data/config/locales/uk.yml
CHANGED
@@ -34,6 +34,7 @@ uk:
|
|
34
34
|
zero: "не додано файлів (максимум -%{max} файли)"
|
35
35
|
one: "занадто багато доданих файлів (максимум -%{max} файлів, отримав %{count})"
|
36
36
|
other: "занадто багато доданих файлів (максимум -%{max} файлів, отримав %{count})"
|
37
|
+
attachment_missing: "не має доданого файлу"
|
37
38
|
media_metadata_missing: "не є допустимим зображенням"
|
38
39
|
dimension_min_not_included_in: "мусить бути більше або дорівнювати %{width} x %{height} пікселям"
|
39
40
|
dimension_max_not_included_in: "мусить бути менше або дорівнювати %{width} x %{height} пікселям"
|
data/config/locales/vi.yml
CHANGED
@@ -34,6 +34,7 @@ vi:
|
|
34
34
|
zero: "không có tệp nào được đính kèm (tối đa là các tệp %{max})"
|
35
35
|
one: "quá nhiều tệp được đính kèm (tối đa là các tệp %{max}, có %{count})"
|
36
36
|
other: "quá nhiều tệp được đính kèm (tối đa là các tệp %{max}, có %{count})"
|
37
|
+
attachment_missing: "không có tập tin đính kèm"
|
37
38
|
media_metadata_missing: "không phải là ảnh"
|
38
39
|
dimension_min_not_included_in: "phải lớn hơn hoặc bằng %{width} x %{height} pixel"
|
39
40
|
dimension_max_not_included_in: "phải nhỏ hơn hoặc bằng %{width} x %{height} pixel"
|
data/config/locales/zh-CN.yml
CHANGED
@@ -34,6 +34,7 @@ zh-CN:
|
|
34
34
|
zero: "未附加文件(最大为%{max}文件)"
|
35
35
|
one: "附加的文件太多(最大为%{max}文件,得到%{count})"
|
36
36
|
other: "附加的文件太多(最大为%{max}文件,得到%{count})"
|
37
|
+
attachment_missing: "没有附件"
|
37
38
|
media_metadata_missing: "不是有效的媒体文件"
|
38
39
|
dimension_min_not_included_in: "必须大于或等于 %{width} x %{height} 像素"
|
39
40
|
dimension_max_not_included_in: "必须小于或等于 %{width} x %{height} 像素"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "open3"
|
4
4
|
|
5
5
|
module ActiveStorageValidations
|
6
6
|
# = ActiveStorageValidations ContentType \Analyzer
|
@@ -41,15 +41,15 @@ module ActiveStorageValidations
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
rescue Errno::ENOENT
|
44
|
-
raise FileCommandLineToolNotInstalledError,
|
44
|
+
raise FileCommandLineToolNotInstalledError, "file command-line tool is not installed"
|
45
45
|
end
|
46
46
|
|
47
47
|
def media_from_path(path)
|
48
48
|
instrument("file") do
|
49
49
|
stdout, status = Open3.capture2(
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
"file",
|
51
|
+
"-b",
|
52
|
+
"--mime-type",
|
53
53
|
path
|
54
54
|
)
|
55
55
|
|
@@ -4,7 +4,6 @@ module ActiveStorageValidations
|
|
4
4
|
# This analyzer relies on the third-party {ruby-vips}[https://github.com/libvips/ruby-vips] gem.
|
5
5
|
# Ruby-vips requires the {libvips}[https://libvips.github.io/libvips/] system library.
|
6
6
|
class Analyzer::ImageAnalyzer::Vips < Analyzer::ImageAnalyzer
|
7
|
-
|
8
7
|
private
|
9
8
|
|
10
9
|
def read_media
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require_relative
|
3
|
+
require "open3"
|
4
|
+
require_relative "shared/asv_ff_probable"
|
5
5
|
|
6
6
|
module ActiveStorageValidations
|
7
7
|
# = ActiveStorageValidations Video \Analyzer
|
@@ -80,7 +80,7 @@ module ActiveStorageValidations
|
|
80
80
|
numerator = Integer(terms[0])
|
81
81
|
denominator = Integer(terms[1])
|
82
82
|
|
83
|
-
[numerator, denominator] unless numerator == 0
|
83
|
+
[ numerator, denominator ] unless numerator == 0
|
84
84
|
end
|
85
85
|
end
|
86
86
|
end
|
@@ -127,4 +127,4 @@ module ActiveStorageValidations
|
|
127
127
|
@container ||= @media["format"] || {}
|
128
128
|
end
|
129
129
|
end
|
130
|
-
end
|
130
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
3
|
+
require_relative "shared/asv_attachable"
|
4
|
+
require_relative "shared/asv_loggable"
|
5
5
|
|
6
6
|
module ActiveStorageValidations
|
7
7
|
# = Active Storage Validations \Analyzer
|
@@ -37,29 +37,30 @@ module ActiveStorageValidations
|
|
37
37
|
raise NotImplementedError
|
38
38
|
end
|
39
39
|
|
40
|
+
# rubocop:disable Metrics/MethodLength
|
40
41
|
def media(tempfile)
|
41
42
|
@media ||= case @attachable
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
43
|
+
when ActiveStorage::Blob, String
|
44
|
+
blob = @attachable.is_a?(String) ? ActiveStorage::Blob.find_signed!(@attachable) : @attachable
|
45
|
+
media_from_tempfile_path(tempfile, blob)
|
46
|
+
when Hash
|
47
|
+
io = @attachable[:io]
|
48
|
+
if io.is_a?(StringIO)
|
49
|
+
media_from_tempfile_path(tempfile, io)
|
50
|
+
else
|
51
|
+
File.open(io) do |file|
|
52
|
+
media_from_path(file.path)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
|
56
|
+
media_from_path(@attachable.path)
|
57
|
+
when File
|
58
|
+
supports_file_attachment? ? media_from_path(@attachable.path) : raise_rails_like_error(@attachable)
|
59
|
+
when Pathname
|
60
|
+
supports_pathname_attachment? ? media_from_path(@attachable.to_s) : raise_rails_like_error(@attachable)
|
61
|
+
else
|
62
|
+
raise_rails_like_error(@attachable)
|
63
|
+
end
|
63
64
|
end
|
64
65
|
|
65
66
|
def media_from_tempfile_path(tempfile, file_representation)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
3
|
+
require_relative "shared/asv_active_storageable"
|
4
|
+
require_relative "shared/asv_analyzable"
|
5
|
+
require_relative "shared/asv_attachable"
|
6
|
+
require_relative "shared/asv_errorable"
|
7
|
+
require_relative "shared/asv_optionable"
|
8
|
+
require_relative "shared/asv_symbolizable"
|
9
9
|
|
10
10
|
module ActiveStorageValidations
|
11
11
|
class AspectRatioValidator < ActiveModel::EachValidator # :nodoc
|
@@ -48,7 +48,7 @@ module ActiveStorageValidations
|
|
48
48
|
private
|
49
49
|
|
50
50
|
def is_valid?(record, attribute, attachable, metadata)
|
51
|
-
|
51
|
+
media_metadata_present?(record, attribute, attachable, metadata) &&
|
52
52
|
authorized_aspect_ratio?(record, attribute, attachable, metadata)
|
53
53
|
end
|
54
54
|
|
@@ -64,11 +64,10 @@ module ActiveStorageValidations
|
|
64
64
|
|
65
65
|
return true if attachable_aspect_ratio_is_authorized
|
66
66
|
|
67
|
-
errors_options =
|
68
|
-
error_type = aspect_ratio_error_mapping
|
69
|
-
errors_options[:authorized_aspect_ratios] = string_aspect_ratios
|
67
|
+
errors_options = initialize_and_populate_error_options(options, attachable)
|
70
68
|
errors_options[:width] = metadata[:width]
|
71
69
|
errors_options[:height] = metadata[:height]
|
70
|
+
error_type = aspect_ratio_error_mapping
|
72
71
|
add_error(record, attribute, error_type, **errors_options)
|
73
72
|
false
|
74
73
|
end
|
@@ -80,13 +79,17 @@ module ActiveStorageValidations
|
|
80
79
|
NAMED_ASPECT_RATIOS.include?(aspect_ratio) ? :"aspect_ratio_not_#{aspect_ratio}" : :aspect_ratio_not_x_y
|
81
80
|
end
|
82
81
|
|
83
|
-
def
|
84
|
-
return
|
82
|
+
def media_metadata_present?(record, attribute, attachable, metadata)
|
83
|
+
return true if metadata[:width].to_i > 0 && metadata[:height].to_i > 0
|
84
|
+
|
85
|
+
add_media_metadata_missing_error(record, attribute, attachable)
|
86
|
+
false
|
87
|
+
end
|
85
88
|
|
89
|
+
def initialize_and_populate_error_options(options, attachable)
|
86
90
|
errors_options = initialize_error_options(options, attachable)
|
87
91
|
errors_options[:authorized_aspect_ratios] = string_aspect_ratios
|
88
|
-
|
89
|
-
true
|
92
|
+
errors_options
|
90
93
|
end
|
91
94
|
|
92
95
|
def valid_square_aspect_ratio?(metadata)
|
@@ -112,7 +115,7 @@ module ActiveStorageValidations
|
|
112
115
|
def ensure_at_least_one_validator_option
|
113
116
|
return if AVAILABLE_CHECKS.any? { |argument| options.key?(argument) }
|
114
117
|
|
115
|
-
raise ArgumentError,
|
118
|
+
raise ArgumentError, "You must pass either :with or :in to the validator"
|
116
119
|
end
|
117
120
|
|
118
121
|
def ensure_aspect_ratio_validity
|
@@ -148,7 +151,7 @@ module ActiveStorageValidations
|
|
148
151
|
|
149
152
|
"#{x}:#{y}"
|
150
153
|
end
|
151
|
-
end.join(
|
154
|
+
end.join(", ")
|
152
155
|
end
|
153
156
|
end
|
154
157
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative "shared/asv_active_storageable"
|
4
|
+
require_relative "shared/asv_errorable"
|
5
|
+
require_relative "shared/asv_symbolizable"
|
6
6
|
|
7
7
|
module ActiveStorageValidations
|
8
8
|
class AttachedValidator < ActiveModel::EachValidator # :nodoc:
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require_relative "shared/asv_active_storageable"
|
4
|
+
require_relative "shared/asv_errorable"
|
5
|
+
require_relative "shared/asv_optionable"
|
6
|
+
require_relative "shared/asv_symbolizable"
|
7
7
|
|
8
8
|
module ActiveStorageValidations
|
9
9
|
class BaseComparisonValidator < ActiveModel::EachValidator # :nodoc:
|
@@ -22,14 +22,14 @@ module ActiveStorageValidations
|
|
22
22
|
|
23
23
|
def initialize(*args)
|
24
24
|
if self.class == BaseComparisonValidator
|
25
|
-
raise NotImplementedError,
|
25
|
+
raise NotImplementedError, "BaseComparisonValidator is an abstract class and cannot be instantiated directly."
|
26
26
|
end
|
27
27
|
super
|
28
28
|
end
|
29
29
|
|
30
30
|
def check_validity!
|
31
31
|
unless AVAILABLE_CHECKS.one? { |argument| options.key?(argument) }
|
32
|
-
raise ArgumentError,
|
32
|
+
raise ArgumentError, "You must pass either :less_than(_or_equal_to), :greater_than(_or_equal_to), or :between to the validator"
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|