active_storage_validations 2.0.4 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +125 -19
  3. data/config/locales/da.yml +9 -0
  4. data/config/locales/de.yml +9 -0
  5. data/config/locales/en-GB.yml +9 -0
  6. data/config/locales/en.yml +9 -0
  7. data/config/locales/es.yml +9 -0
  8. data/config/locales/fr.yml +9 -0
  9. data/config/locales/it.yml +9 -0
  10. data/config/locales/ja.yml +55 -46
  11. data/config/locales/nl.yml +9 -0
  12. data/config/locales/pl.yml +9 -0
  13. data/config/locales/pt-BR.yml +9 -0
  14. data/config/locales/ru.yml +9 -0
  15. data/config/locales/sv.yml +10 -1
  16. data/config/locales/tr.yml +9 -0
  17. data/config/locales/uk.yml +9 -0
  18. data/config/locales/vi.yml +9 -0
  19. data/config/locales/zh-CN.yml +9 -0
  20. data/lib/active_storage_validations/analyzer/pdf_analyzer.rb +89 -0
  21. data/lib/active_storage_validations/base_comparison_validator.rb +13 -1
  22. data/lib/active_storage_validations/duration_validator.rb +1 -0
  23. data/lib/active_storage_validations/matchers/base_comparison_validator_matcher.rb +11 -1
  24. data/lib/active_storage_validations/matchers/pages_validator_matcher.rb +39 -0
  25. data/lib/active_storage_validations/matchers.rb +1 -0
  26. data/lib/active_storage_validations/pages_validator.rb +61 -0
  27. data/lib/active_storage_validations/shared/asv_analyzable.rb +6 -0
  28. data/lib/active_storage_validations/shared/asv_attachable.rb +1 -1
  29. data/lib/active_storage_validations/size_validator.rb +1 -0
  30. data/lib/active_storage_validations/total_size_validator.rb +1 -0
  31. data/lib/active_storage_validations/version.rb +1 -1
  32. data/lib/active_storage_validations.rb +2 -0
  33. metadata +8 -2
@@ -2,53 +2,62 @@ ja:
2
2
  errors:
3
3
  messages:
4
4
  content_type_invalid:
5
- one: "無効なコンテンツタイプがあります(許可されたコンテンツタイプは%{authorized_human_content_types}です)"
6
- other: "無効なコンテンツタイプがあります(許可されたコンテンツタイプは%{authorized_human_content_types}です)"
5
+ one: "のファイルタイプは許可されていません (許可されたファイルタイプは%{authorized_human_content_types})"
6
+ other: "のファイルタイプは許可されていません (許可されたファイルタイプは%{authorized_human_content_types})"
7
7
  content_type_spoofed:
8
- one: "コンテンツを通じて検出されたものと同等ではないコンテンツタイプがあります(許可されたコンテンツタイプは%{authorized_human_content_types}です)"
9
- other: "コンテンツを通じて検出されたものと同等ではないコンテンツタイプがあります(承認されたコンテンツタイプは%{authorized_human_content_types}です)"
10
- file_size_not_less_than: "ファイル サイズは %{max} 未満にする必要があります (現在のサイズは %{file_size})"
11
- file_size_not_less_than_or_equal_to: "ファイル サイズは %{max} 以下である必要があります (現在のサイズは %{file_size})"
12
- file_size_not_greater_than: "ファイル サイズは %{min} より大きい必要があります (現在のサイズは %{file_size} です)"
13
- file_size_not_greater_than_or_equal_to: "ファイル サイズは %{min} 以上である必要があります (現在のサイズは %{file_size})"
14
- file_size_not_between: "ファイル サイズは %{min} から %{max} の間でなければなりません (現在のサイズは %{file_size} です)"
15
- total_file_size_not_less_than: "ファイルの合計サイズは %{max} 未満である必要があります (現在のサイズは %{total_file_size})"
16
- total_file_size_not_less_than_or_equal_to: "ファイルの合計サイズは %{max} 以下である必要があります (現在のサイズは %{total_file_size})"
17
- total_file_size_not_greater_than: "ファイルの合計サイズは %{min} より大きくなければなりません (現在のサイズは %{total_file_size} です)"
18
- total_file_size_not_greater_than_or_equal_to: "ファイルの合計サイズは %{min} 以上である必要があります (現在のサイズは %{total_file_size})"
19
- total_file_size_not_between: "ファイルの合計サイズは %{min} から %{max} までである必要があります (現在のサイズは %{total_file_size})"
20
- duration_not_less_than: "期間は%{max}未満である必要があります(現在の期間は%{duration})"
21
- duration_not_less_than_or_equal_to: "期間は%{max}以下でなければなりません(現在の期間は%{duration})"
22
- duration_not_greater_than: "期間は%{min}より大きくなければなりません(現在の期間は%{duration}です)"
23
- duration_not_greater_than_or_equal_to: "期間は%{min}以上である必要があります(現在の期間は%{duration})"
24
- duration_not_between: "期間は%{min}と%{max}の間でなければなりません(現在の期間は%{duration})"
8
+ one: "のファイルタイプがファイル内容から検出されたものと異なります (許可されたファイルタイプは%{authorized_human_content_types})"
9
+ other: "のファイルタイプがファイル内容から検出されたものと異なります (許可されたファイルタイプは%{authorized_human_content_types})"
10
+ file_size_not_less_than: "のファイルサイズは%{max}未満にしてください (添付ファイルのサイズは%{file_size})"
11
+ file_size_not_less_than_or_equal_to: "のファイルサイズは%{max}以下にしてください (添付ファイルのサイズは%{file_size})"
12
+ file_size_not_greater_than: "のファイルサイズは%{min}より大きくしてください (添付ファイルのサイズは%{file_size})"
13
+ file_size_not_greater_than_or_equal_to: "のファイルサイズは%{min}以上にしてください (添付ファイルのサイズは%{file_size})"
14
+ file_size_not_between: "のファイルサイズは%{min}以上%{max}以下にしてください (添付ファイルのサイズは%{file_size})"
15
+ file_size_not_equal_to: "のファイルサイズは%{exact}にしてください (添付ファイルのサイズは%{file_size})"
16
+ total_file_size_not_less_than: "のファイルサイズの合計は%{max}未満にしてください (添付ファイルのサイズは%{total_file_size})"
17
+ total_file_size_not_less_than_or_equal_to: "のファイルサイズの合計は%{max}以下にしてください (添付ファイルのサイズは%{total_file_size})"
18
+ total_file_size_not_greater_than: "のファイルサイズの合計は%{min}より大きくしてください (添付ファイルのサイズは%{total_file_size})"
19
+ total_file_size_not_greater_than_or_equal_to: "のファイルサイズの合計は%{min}以上してください (添付ファイルのサイズは%{total_file_size})"
20
+ total_file_size_not_between: "のファイルサイズの合計は%{min}以上%{max}以下にしてください (添付ファイルのサイズは%{total_file_size})"
21
+ total_file_size_not_equal_to: "のファイルサイズの合計は%{exact}にしてください (添付ファイルのサイズは%{total_file_size})"
22
+ duration_not_less_than: "の再生時間は%{max}未満にしてください (添付ファイルの再生時間は%{duration})"
23
+ duration_not_less_than_or_equal_to: "の再生時間は%{max}以下にしてください (添付ファイルの再生時間は%{duration})"
24
+ duration_not_greater_than: "の再生時間は%{min}より大きくしてください (添付ファイルの再生時間は%{duration})"
25
+ duration_not_greater_than_or_equal_to: "の再生時間は%{min}以上にしてください (添付ファイルの再生時間は%{duration})"
26
+ duration_not_between: "の再生時間は%{min}以上%{max}以下にしてください (添付ファイルの再生時間は%{duration})"
27
+ duration_not_equal_to: "の再生時間は%{exact}にしてください (添付ファイルの再生時間は%{duration})"
25
28
  limit_out_of_range:
26
- zero: "添付されたファイルはありません(%{min}と%{max}ファイルの間にある必要があります)"
27
- one: "1つのファイルのみが添付されています(%{min}と%{max}ファイルの間にある必要があります)"
28
- other: "ファイルの総数は、%{min}と%{max}ファイルの間でなければなりません(%{count}ファイルが添付されています)"
29
+ zero: "には%{min}件以上%{max}以下のファイルを添付してください (添付されたファイルは%{count}件)"
30
+ one: "には%{min}件以上%{max}以下のファイルを添付してください (添付されたファイルは%{count}件)"
31
+ other: "には%{min}件以上%{max}以下のファイルを添付してください (添付されたファイルは%{count})"
29
32
  limit_min_not_reached:
30
- zero: "添付されたファイルはありません(少なくとも%{min}ファイルが必要です)"
31
- one: "1つのファイルのみが添付されています(少なくとも%{min}ファイルが必要です)"
32
- other: "%{count}添付ファイル(少なくとも%{min}ファイルが必要です)"
33
+ zero: "には%{min}件以上のファイルを添付してください (添付されたファイルは%{count}件)"
34
+ one: "には%{min}件以上のファイルを添付してください (添付されたファイルは%{count}件)"
35
+ other: "には%{min}件以上のファイルを添付してください (添付されたファイルは%{count})"
33
36
  limit_max_exceeded:
34
- zero: "添付されたファイルはありません(最大は%{max}ファイル)"
35
- one: "添付されているファイルが多すぎます(最大は%{max}ファイル、%{count})"
36
- other: "添付されているファイルが多すぎます(最大は%{max}ファイル、%{count})"
37
- attachment_missing: "添付ファイルがありません"
38
- media_metadata_missing: "有効なメディアファイルではありません"
39
- dimension_min_not_included_in: "は %{width} x %{height} ピクセル以上の大きさにしてください"
40
- dimension_max_not_included_in: "は %{width} x %{height} ピクセル以下の大きさにしてください"
41
- dimension_width_not_included_in: "の横幅は %{min} ピクセル以上 %{max} ピクセル以下にしてください"
42
- dimension_height_not_included_in: "の縦幅は %{min} ピクセル以上 %{max} ピクセル以下にしてください"
43
- dimension_width_not_greater_than_or_equal_to: "の横幅は %{length} ピクセル以上にしてください"
44
- dimension_height_not_greater_than_or_equal_to: "の縦幅は %{length} ピクセル以上にしてください"
45
- dimension_width_not_less_than_or_equal_to: "の横幅は %{length} ピクセル以下にしてください"
46
- dimension_height_not_less_than_or_equal_to: "の縦幅は %{length} ピクセル以下にしてください"
47
- dimension_width_not_equal_to: "の横幅は %{length} ピクセルにしてください"
48
- dimension_height_not_equal_to: "の縦幅は %{length} ピクセルにしてください"
49
- aspect_ratio_not_square: "は正方形である必要があります(現在のファイルは%{width}x%{height})"
50
- aspect_ratio_not_portrait: "は縦長である必要があります(現在のファイルは%{width}x%{height})"
51
- aspect_ratio_not_landscape: "は横長である必要があります(現在のファイルは%{width}x%{height})"
52
- aspect_ratio_not_x_y: "は%{authorized_aspect_ratios}である必要があります(現在のファイルは%{width}x%{height})"
53
- aspect_ratio_invalid: "は無効なアスペクト比です(有効なアスペクト比は%{authorized_aspect_ratios}です)"
54
- file_not_processable: "は無効なメディアファイルです"
37
+ zero: "には%{max}件以下のファイルを添付してください (添付されたファイルは%{count}件)"
38
+ one: "には%{max}件以下のファイルを添付してください (添付されたファイルは%{count})"
39
+ other: "には%{max}件以下のファイルを添付してください (添付されたファイルは%{count})"
40
+ attachment_missing: "にファイルを添付してください"
41
+ media_metadata_missing: "のメディアのメタデータを検出できません"
42
+ dimension_min_not_included_in: "の解像度は%{width}x%{height}ピクセル以上にしてください"
43
+ dimension_max_not_included_in: "の解像度は%{width}x%{height}ピクセル以下にしてください"
44
+ dimension_width_not_included_in: "の横幅は%{min}ピクセル以上%{max}ピクセル以下にしてください"
45
+ dimension_height_not_included_in: "の縦幅は%{min}ピクセル以上%{max}ピクセル以下にしてください"
46
+ dimension_width_not_greater_than_or_equal_to: "の横幅は%{length}ピクセル以上にしてください"
47
+ dimension_height_not_greater_than_or_equal_to: "の縦幅は%{length}ピクセル以上にしてください"
48
+ dimension_width_not_less_than_or_equal_to: "の横幅は%{length}ピクセル以下にしてください"
49
+ dimension_height_not_less_than_or_equal_to: "の縦幅は%{length}ピクセル以下にしてください"
50
+ dimension_width_not_equal_to: "の横幅は%{length}ピクセルにしてください"
51
+ dimension_height_not_equal_to: "の縦幅は%{length}ピクセルにしてください"
52
+ aspect_ratio_not_square: "のアスペクト比は等しくしてください (添付されたメディアの解像度は%{width}x%{height})"
53
+ aspect_ratio_not_portrait: "のアスペクト比は縦長にしてください (添付されたメディアの解像度は%{width}x%{height})"
54
+ aspect_ratio_not_landscape: "のアスペクト比は横長にしてください (添付されたメディアの解像度は%{width}x%{height})"
55
+ aspect_ratio_not_x_y: "のアスペクト比は%{authorized_aspect_ratios}にしてください (添付されたメディアの解像度は%{width}x%{height})"
56
+ aspect_ratio_invalid: "のアスペクト比を検出できません (許可されたアスペクト比は%{authorized_aspect_ratios})"
57
+ file_not_processable: "のメディアを処理できません"
58
+ pages_not_less_than: "のページ数は%{max}未満にしてください (添付されたファイルは%{pages}ページ)"
59
+ pages_not_less_than_or_equal_to: "のページ数は%{max}以下にしてください (添付されたファイルは%{pages}ページ)"
60
+ pages_not_greater_than: "のページ数は%{min}より大きくしてください (添付されたファイルは%{pages}ページ)"
61
+ pages_not_greater_than_or_equal_to: "のページ数は%{min}以上にしてください (添付されたファイルは%{pages}ページ)"
62
+ pages_not_between: "のページ数は%{min}以上%{max}以下にしてください (添付されたファイルは%{pages}ページ)"
63
+ pages_not_equal_to: "のページ数は%{exact}にしてください (添付されたファイルは%{pages}ページ)"
@@ -12,16 +12,19 @@ nl:
12
12
  file_size_not_greater_than: "bestandsgrootte moet groter zijn dan %{min} (huidige grootte is %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "bestandsgrootte moet groter zijn dan of gelijk zijn aan %{min} (huidige grootte is %{file_size})"
14
14
  file_size_not_between: "bestandsgrootte moet tussen %{min} en %{max} liggen (huidige grootte is %{file_size})"
15
+ file_size_not_equal_to: "bestandsgrootte moet gelijk zijn aan %{exact} (huidige grootte is %{file_size})"
15
16
  total_file_size_not_less_than: "totale bestandsgrootte moet kleiner zijn dan %{max} (huidige grootte is %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "totale bestandsgrootte moet kleiner zijn dan of gelijk zijn aan %{max} (huidige grootte is %{total_file_size})"
17
18
  total_file_size_not_greater_than: "totale bestandsgrootte moet groter zijn dan %{min} (huidige grootte is %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "totale bestandsgrootte moet groter zijn dan of gelijk zijn aan %{min} (huidige grootte is %{total_file_size})"
19
20
  total_file_size_not_between: "totale bestandsgrootte moet tussen %{min} en %{max} liggen (huidige grootte is %{total_file_size})"
21
+ total_file_size_not_equal_to: "totale bestandsgrootte moet gelijk zijn aan %{exact} (huidige grootte is %{total_file_size})"
20
22
  duration_not_less_than: "duur moet kleiner zijn dan %{max} (huidige duur is %{duration})"
21
23
  duration_not_less_than_or_equal_to: "duur moet kleiner zijn dan of gelijk zijn aan %{max} (huidige duur is %{duration})"
22
24
  duration_not_greater_than: "duur moet groter zijn dan %{min} (huidige duur is %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "duur moet groter zijn dan of gelijk zijn aan %{min} (huidige duur is %{duration})"
24
26
  duration_not_between: "duur moet tussen %{min} en %{max} zijn (huidige duur is %{duration})"
27
+ duration_not_equal_to: "duur moet gelijk zijn aan %{exact} (huidige duur is %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "geen bestanden bijgevoegd (moet tussen %{min} en %{max} bestanden hebben)"
27
30
  one: "slechts 1 bijgevoegd bestand (moet tussen %{min} en %{max} bestanden hebben)"
@@ -52,3 +55,9 @@ nl:
52
55
  aspect_ratio_not_x_y: "moet %{authorized_aspect_ratios} zijn (huidig bestand is %{width}x%{height}px)"
53
56
  aspect_ratio_invalid: "heeft een ongeldige beeldverhouding (geldige beeldverhoudingen zijn %{authorized_aspect_ratios})"
54
57
  file_not_processable: "wordt niet geïdentificeerd als een geldig mediabestand"
58
+ pages_not_less_than: "het aantal pagina's moet kleiner zijn dan %{max} (het huidige aantal pagina's is %{pages})"
59
+ pages_not_less_than_or_equal_to: "het aantal pagina's moet kleiner zijn dan of gelijk zijn aan %{max} (het huidige aantal pagina's is %{pages})"
60
+ pages_not_greater_than: "het aantal pagina's moet groter zijn dan %{min} (het huidige aantal pagina's is %{pages})"
61
+ pages_not_greater_than_or_equal_to: "het aantal pagina's moet groter zijn dan of gelijk zijn aan %{min} (het huidige aantal pagina's is %{pages})"
62
+ pages_not_between: "het aantal pagina's moet tussen %{min} en %{max} liggen (het huidige aantal pagina's is %{pages})"
63
+ pages_not_equal_to: "het aantal pagina's moet gelijk zijn aan %{exact} (het huidige aantal pagina's is %{pages})"
@@ -12,16 +12,19 @@ pl:
12
12
  file_size_not_greater_than: "rozmiar pliku musi być większy niż %{min} (obecny rozmiar to %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "rozmiar pliku musi być większy lub równy %{min} (obecny rozmiar to %{file_size})"
14
14
  file_size_not_between: "rozmiar pliku musi mieścić się w przedziale od %{min} do %{max} (obecny rozmiar to %{file_size})"
15
+ file_size_not_equal_to: "rozmiar pliku musi być równy %{exact} (obecny rozmiar to %{file_size})"
15
16
  total_file_size_not_less_than: "całkowity rozmiar pliku musi być mniejszy niż %{max} (obecny rozmiar to %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "całkowity rozmiar pliku musi być mniejszy lub równy %{max} (obecny rozmiar to %{total_file_size})"
17
18
  total_file_size_not_greater_than: "całkowity rozmiar pliku musi być większy niż %{min} (obecny rozmiar to %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "całkowity rozmiar pliku musi być większy lub równy %{min} (obecny rozmiar to %{total_file_size})"
19
20
  total_file_size_not_between: "całkowity rozmiar pliku musi mieścić się w przedziale od %{min} do %{max} (obecny rozmiar to %{total_file_size})"
21
+ total_file_size_not_equal_to: "całkowity rozmiar pliku musi być równy %{exact} (obecny rozmiar to %{total_file_size})"
20
22
  duration_not_less_than: "czas trwania musi być mniejszy niż %{max} (obecny czas trwania wynosi %{duration})"
21
23
  duration_not_less_than_or_equal_to: "czas trwania musi być mniejszy lub równy %{max} (obecny czas trwania wynosi %{duration})"
22
24
  duration_not_greater_than: "czas trwania musi być większy niż %{min} (obecny czas trwania wynosi %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "czas trwania musi być większy lub równy %{min} (obecny czas trwania wynosi %{duration})"
24
26
  duration_not_between: "czas trwania musi wynosić między %{min} a %{max} (obecny czas trwania wynosi %{duration})"
27
+ duration_not_equal_to: "czas trwania musi być równy %{exact} (obecny czas trwania wynosi %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "brak dołączonych plików (musi mieć między %{min} a %{max} pliki)"
27
30
  one: "załączony tylko 1 plik (musi mieć między %{min} a %{max} pliki)"
@@ -52,3 +55,9 @@ pl:
52
55
  aspect_ratio_not_x_y: "musi być %{authorized_aspect_ratios} (bieżący plik to %{width}x%{height}px)"
53
56
  aspect_ratio_invalid: "ma nieprawidłowy współczynnik kształtu (ważne współczynniki kształtu wynoszą %{authorized_aspect_ratios})"
54
57
  file_not_processable: "nie jest identyfikowany jako prawidłowy plik multimedialny"
58
+ pages_not_less_than: "liczba stron musi być mniejsza niż %{max} (bieżąca liczba stron to %{pages})"
59
+ pages_not_less_than_or_equal_to: "liczba stron musi być mniejsza lub równa %{max} (bieżąca liczba stron to %{pages})"
60
+ pages_not_greater_than: "liczba stron musi być większa niż %{min} (bieżąca liczba stron to %{pages})"
61
+ pages_not_greater_than_or_equal_to: "liczba stron musi być większa lub równa %{min} (bieżąca liczba stron to %{pages})"
62
+ pages_not_between: "liczba stron musi być między %{min} a %{max} (bieżąca liczba stron to %{pages})"
63
+ pages_not_equal_to: "liczba stron musi być równa %{exact} (bieżąca liczba stron to %{pages})"
@@ -12,16 +12,19 @@ pt-BR:
12
12
  file_size_not_greater_than: "o tamanho do arquivo deve ser maior que %{min} (o tamanho atual é %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "o tamanho do arquivo deve ser maior ou igual a %{min} (o tamanho atual é %{file_size})"
14
14
  file_size_not_between: "o tamanho do arquivo deve estar entre %{min} e %{max} (o tamanho atual é %{file_size})"
15
+ file_size_not_equal_to: "o tamanho do arquivo deve ser igual a %{exact} (o tamanho atual é %{file_size})"
15
16
  total_file_size_not_less_than: "o tamanho total do arquivo deve ser menor que %{max} (o tamanho atual é %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "o tamanho total do arquivo deve ser menor ou igual a %{max} (o tamanho atual é %{total_file_size})"
17
18
  total_file_size_not_greater_than: "o tamanho total do arquivo deve ser maior que %{min} (o tamanho atual é %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "o tamanho total do arquivo deve ser maior ou igual a %{min} (o tamanho atual é %{total_file_size})"
19
20
  total_file_size_not_between: "o tamanho total do arquivo deve estar entre %{min} e %{max} (o tamanho atual é %{total_file_size})"
21
+ total_file_size_not_equal_to: "o tamanho total do arquivo deve ser igual a %{exact} (o tamanho atual é %{total_file_size})"
20
22
  duration_not_less_than: "a duração deve ser inferior a %{max} (a duração atual é %{duration})"
21
23
  duration_not_less_than_or_equal_to: "a duração deve ser inferior ou igual a %{max} (a duração atual é %{duration})"
22
24
  duration_not_greater_than: "a duração tem de ser superior a %{min} (a duração atual é %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "a duração deve ser maior ou igual a %{min} (a duração atual é %{duration})"
24
26
  duration_not_between: "a duração deve estar entre %{min} e %{max} (a duração atual é %{duration})"
27
+ duration_not_equal_to: "a duração deve ser igual a %{exact} (a duração atual é %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "nenhum arquivo anexado (deve ter entre %{min} e %{max})"
27
30
  one: "apenas 1 arquivo anexado (deve ter entre %{min} e %{max})"
@@ -52,3 +55,9 @@ pt-BR:
52
55
  aspect_ratio_not_x_y: "deve ser %{authorized_aspect_ratios} (o arquivo atual é %{width}x%{height}px)"
53
56
  aspect_ratio_invalid: "tem uma proporção inválida (as proporções válidas são %{authorized_aspect_ratios})"
54
57
  file_not_processable: "não é identificado como um arquivo de mídia válido"
58
+ pages_not_less_than: "a contagem de páginas deve ser menor que %{max} (a contagem atual de páginas é %{pages})"
59
+ pages_not_less_than_or_equal_to: "a contagem de páginas deve ser menor ou igual a %{max} (a contagem atual de páginas é %{pages})"
60
+ pages_not_greater_than: "a contagem de páginas deve ser maior que %{min} (a contagem atual de páginas é %{pages})"
61
+ pages_not_greater_than_or_equal_to: "a contagem de páginas deve ser maior ou igual a %{min} (a contagem atual de páginas é %{pages})"
62
+ pages_not_between: "a contagem de páginas deve estar entre %{min} e %{max} (a contagem atual de páginas é %{pages})"
63
+ pages_not_equal_to: "a contagem de páginas deve ser igual a %{exact} (a contagem atual de páginas é %{pages})"
@@ -12,16 +12,19 @@ ru:
12
12
  file_size_not_greater_than: "размер файла должен быть больше %{min} (текущий размер %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "размер файла должен быть больше или равен %{min} (текущий размер %{file_size})"
14
14
  file_size_not_between: "размер файла должен быть между %{min} и %{max} (текущий размер %{file_size})"
15
+ file_size_not_equal_to: "размер файла должен быть равен %{exact} (текущий размер %{file_size})"
15
16
  total_file_size_not_less_than: "общий размер файла должен быть меньше %{max} (текущий размер %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "общий размер файла должен быть меньше или равен %{max} (текущий размер %{total_file_size})"
17
18
  total_file_size_not_greater_than: "общий размер файла должен быть больше %{min} (текущий размер %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "общий размер файла должен быть больше или равен %{min} (текущий размер %{total_file_size})"
19
20
  total_file_size_not_between: "общий размер файла должен быть между %{min} и %{max} (текущий размер %{total_file_size})"
21
+ total_file_size_not_equal_to: "общий размер файла должен быть равен %{exact} (текущий размер %{total_file_size})"
20
22
  duration_not_less_than: "длительность должна быть меньше %{max} (текущая продолжительность составляет %{duration})"
21
23
  duration_not_less_than_or_equal_to: "длительность должна быть меньше или равна %{max} (текущая продолжительность составляет %{duration})"
22
24
  duration_not_greater_than: "длительность должна быть больше %{min} (текущая продолжительность составляет %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "длительность должна быть больше или равна %{min} (текущая продолжительность составляет %{duration})"
24
26
  duration_not_between: "длительность должна быть между %{min} и %{max} (текущая продолжительность составляет %{duration})"
27
+ duration_not_equal_to: "длительность должна быть равна %{exact} (текущая продолжительность составляет %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "никаких файлов не прилагается (должно иметь от %{min} до %{max} файлов)"
27
30
  one: "прилагается только 1 файл (должно иметь от %{min} до %{max} файлов)"
@@ -52,3 +55,9 @@ ru:
52
55
  aspect_ratio_not_x_y: "должно быть %{authorized_aspect_ratios} (текущий файл %{width}x%{height} пикселей)"
53
56
  aspect_ratio_invalid: "имеет недействительное соотношение сторон (действительные соотношения сторон %{authorized_aspect_ratios})"
54
57
  file_not_processable: "не идентифицируется как действительный медиафайл"
58
+ pages_not_less_than: "количество страниц должно быть меньше %{max} (текущее количество страниц %{pages})"
59
+ pages_not_less_than_or_equal_to: "количество страниц должно быть меньше или равно %{max} (текущее количество страниц %{pages})"
60
+ pages_not_greater_than: "количество страниц должно быть больше %{min} (текущее количество страниц %{pages})"
61
+ pages_not_greater_than_or_equal_to: "количество страниц должно быть больше или равно %{min} (текущее количество страниц %{pages})"
62
+ pages_not_between: "количество страниц должно быть между %{min} и %{max} (текущее количество страниц %{pages})"
63
+ pages_not_equal_to: "количество страниц должно быть равно %{exact} (текущее количество страниц %{pages})"
@@ -12,16 +12,19 @@ sv:
12
12
  file_size_not_greater_than: "filstorleken måste vara större än %{min} (nuvarande storlek är %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "filstorleken måste vara större än eller lika med %{min} (nuvarande storlek är %{file_size})"
14
14
  file_size_not_between: "filstorleken måste vara mellan %{min} och %{max} (nuvarande storlek är %{file_size})"
15
+ file_size_not_equal_to: "filstorleken måste vara lika med %{exact} (nuvarande storlek är %{file_size})"
15
16
  total_file_size_not_less_than: "total filstorlek måste vara mindre än %{max} (nuvarande storlek är %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "total filstorlek måste vara mindre än eller lika med %{max} (nuvarande storlek är %{total_file_size})"
17
18
  total_file_size_not_greater_than: "total filstorlek måste vara större än %{min} (nuvarande storlek är %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "total filstorlek måste vara större än eller lika med %{min} (nuvarande storlek är %{total_file_size})"
19
20
  total_file_size_not_between: "total filstorlek måste vara mellan %{min} och %{max} (nuvarande storlek är %{total_file_size})"
21
+ total_file_size_not_equal_to: "total filstorlek måste vara lika med %{exact} (nuvarande storlek är %{total_file_size})"
20
22
  duration_not_less_than: "varaktigheten måste vara mindre än %{max} (nuvarande varaktighet är %{varaktighet})"
21
23
  duration_not_less_than_or_equal_to: "varaktigheten måste vara mindre än eller lika med %{max} (nuvarande varaktighet är %{varaktighet})"
22
24
  duration_not_greater_than: "varaktigheten måste vara större än %{min} (nuvarande varaktighet är %{varaktighet})"
23
25
  duration_not_greater_than_or_equal_to: "varaktigheten måste vara större än eller lika med %{min} (nuvarande varaktighet är %{varaktighet})"
24
- duration_not_between: "varaktighet måste vara mellan %{min} och %{max} (nuvarande varaktighet är %{varaktighet})"
26
+ duration_not_between: "varaktigheten måste vara mellan %{min} och %{max} (nuvarande varaktighet är %{varaktighet})"
27
+ duration_not_equal_to: "varaktigheten måste vara lika med %{exact} (nuvarande varaktighet är %{varaktighet})"
25
28
  limit_out_of_range:
26
29
  zero: "inga filer bifogade (måste ha mellan %{min} och %{max} filer)"
27
30
  one: "endast en fil bifogad (måste ha mellan %{min} och %{max} filer)"
@@ -52,3 +55,9 @@ sv:
52
55
  aspect_ratio_not_x_y: "måste vara% { authorized_aspect_ratios } (nuvarande fil är %{width}x%{height} pixlar)"
53
56
  aspect_ratio_invalid: "har ett ogiltigt bildförhållande (giltiga bildförhållanden är %{förväntat_aspect_ratios})"
54
57
  file_not_processable: "identifieras inte som en giltig mediefil"
58
+ pages_not_less_than: "sidantal måste vara mindre än %{max} (nuvarande sidantal är %{pages})"
59
+ pages_not_less_than_or_equal_to: "sidantal måste vara mindre än eller lika med %{max} (nuvarande antal sidor är %{pages})"
60
+ pages_not_greater_than: "sidantal måste vara större än %{min} (nuvarande sidantal är %{pages})"
61
+ pages_not_greater_than_or_equal_to: "sidantal måste vara större än eller lika med %{min} (nuvarande antal sidor är %{pages})"
62
+ pages_not_between: "sidantal måste vara mellan %{min} och %{max} (nuvarande antal sidor är %{pages})"
63
+ pages_not_equal_to: "sidantal måste vara lika med %{exact} (nuvarande sidantal är %{pages})"
@@ -12,16 +12,19 @@ tr:
12
12
  file_size_not_greater_than: "dosya boyutu %{min} boyutundan büyük olmalıdır (geçerli boyut %{file_size}'dir)"
13
13
  file_size_not_greater_than_or_equal_to: "dosya boyutu %{min} değerinden büyük veya eşit olmalıdır (geçerli boyut %{file_size}'dir)"
14
14
  file_size_not_between: "dosya boyutu %{min} ile %{max} arasında olmalıdır (geçerli boyut %{file_size}'dir)"
15
+ file_size_not_equal_to: "dosya boyutu %{exact} değerine eşit olmalıdır (geçerli boyut %{file_size}'dir)"
15
16
  total_file_size_not_less_than: "toplam dosya boyutu %{max} boyutundan küçük olmalıdır (geçerli boyut %{total_file_size}'dir)"
16
17
  total_file_size_not_less_than_or_equal_to: "toplam dosya boyutu %{max} değerinden küçük veya ona eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
17
18
  total_file_size_not_greater_than: "toplam dosya boyutu %{min} boyutundan büyük olmalıdır (geçerli boyut %{total_file_size}'dir)"
18
19
  total_file_size_not_greater_than_or_equal_to: "toplam dosya boyutu %{min} değerinden büyük veya eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
19
20
  total_file_size_not_between: "toplam dosya boyutu %{min} ile %{max} arasında olmalıdır (geçerli boyut %{total_file_size}'dir)"
21
+ total_file_size_not_equal_to: "toplam dosya boyutu %{exact} değerine eşit olmalıdır (geçerli boyut %{total_file_size}'dir)"
20
22
  duration_not_less_than: "süre %{max} değerinden az olmalıdır (geçerli süre %{duration})"
21
23
  duration_not_less_than_or_equal_to: "süre %{max} değerine eşit veya daha düşük olmalıdır (geçerli süre %{duration})"
22
24
  duration_not_greater_than: "süre %{min} değerinden büyük olmalıdır (geçerli süre %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "süre %{min} değerine eşit veya daha büyük olmalıdır (geçerli süre %{duration})"
24
26
  duration_not_between: "süre %{min} ile %{max} arasında olmalıdır (geçerli süre %{duration})"
27
+ duration_not_equal_to: "süre %{exact} değerine eşit olmalıdır (geçerli süre %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "dosya eklenmedi ( %{min} ve %{max} dosyaları arasında olmalıdır)"
27
30
  one: "yalnızca 1 dosya eklenmiş ( %{min} ve %{max} dosyaları arasında olmalıdır)"
@@ -52,3 +55,9 @@ tr:
52
55
  aspect_ratio_not_x_y: "%{authorized_aspect_ratios} olmalıdır (geçerli dosya %{width}x%{height}px)"
53
56
  aspect_ratio_invalid: "geçersiz bir en boy oranına sahiptir (geçerli en boy oranları %{authorized_aspect_ratios})"
54
57
  file_not_processable: "geçerli bir medya dosyası olarak tanımlanmadı"
58
+ pages_not_less_than: "sayfa sayısı %{max} değerinden az olmalıdır (geçerli sayfa sayısı %{pages})"
59
+ pages_not_less_than_or_equal_to: "sayfa sayısı %{max} değerinden az veya eşit olmalıdır (geçerli sayfa sayısı %{pages})"
60
+ pages_not_greater_than: "sayfa sayısı %{min} değerinden fazla olmalıdır (geçerli sayfa sayısı %{pages})"
61
+ pages_not_greater_than_or_equal_to: "sayfa sayısı %{min} değerinden fazla veya eşit olmalıdır (geçerli sayfa sayısı %{pages})"
62
+ pages_not_between: "sayfa sayısı %{min} ile %{max} arasında olmalıdır (geçerli sayfa sayısı %{pages})"
63
+ pages_not_equal_to: "sayfa sayısı %{exact} değerine eşit olmalıdır (geçerli sayfa sayısı %{pages})"
@@ -12,16 +12,19 @@ uk:
12
12
  file_size_not_greater_than: "розмір файлу має бути більшим ніж %{min} (поточний розмір %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "розмір файлу має бути більшим або дорівнювати %{min} (поточний розмір %{file_size})"
14
14
  file_size_not_between: "розмір файлу має бути від %{min} до %{max} (поточний розмір %{file_size})"
15
+ file_size_not_equal_to: "розмір файлу має бути рівний %{exact} (поточний розмір %{file_size})"
15
16
  total_file_size_not_less_than: "загальний розмір файлу має бути менше %{max} (поточний розмір %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "загальний розмір файлу має бути меншим або дорівнювати %{max} (поточний розмір %{total_file_size})"
17
18
  total_file_size_not_greater_than: "загальний розмір файлу має бути більшим ніж %{min} (поточний розмір %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "загальний розмір файлу має бути більшим або дорівнювати %{min} (поточний розмір %{total_file_size})"
19
20
  total_file_size_not_between: "загальний розмір файлу має бути від %{min} до %{max} (поточний розмір %{total_file_size})"
21
+ total_file_size_not_equal_to: "загальний розмір файлу має бути рівний %{exact} (поточний розмір %{total_file_size})"
20
22
  duration_not_less_than: "тривалість повинна бути меншою ніж %{max} (поточна тривалість становить %{duration})"
21
23
  duration_not_less_than_or_equal_to: "тривалість повинна бути меншою або дорівнює %{max} (поточна тривалість становить %{duration})"
22
24
  duration_not_greater_than: "тривалість повинна бути більше %{min} (поточна тривалість становить %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "тривалість повинна бути більшою або дорівнює %{min} (поточна тривалість становить %{duration})"
24
26
  duration_not_between: "тривалість повинна бути між %{min} і %{max} (поточна тривалість становить %{duration})"
27
+ duration_not_equal_to: "тривалість повинна бути рівна %{exact} (поточна тривалість становить %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "немає доданих файлів (повинно мати між %{min} і %{max} файли)"
27
30
  one: "додається лише 1 файл (повинен мати між %{min} і %{max} файли)"
@@ -52,3 +55,9 @@ uk:
52
55
  aspect_ratio_not_x_y: "повинен бути %{authorized_aspect_ratios} (поточний файл становить %{width}x%{height} пікселям)"
53
56
  aspect_ratio_invalid: "має недійсне співвідношення сторін (дійсні співвідношення сторін %{authorized_aspect_ratios})"
54
57
  file_not_processable: "не ідентифікується як дійсний медіа-файл"
58
+ pages_not_less_than: "кількість сторінок має бути менше %{max} (поточна кількість сторінок %{pages})"
59
+ pages_not_less_than_or_equal_to: "кількість сторінок має бути меншою або дорівнювати %{max} (поточна кількість сторінок становить %{pages})"
60
+ pages_not_greater_than: "кількість сторінок має бути більшою за %{min} (поточна кількість сторінок становить %{pages})"
61
+ pages_not_greater_than_or_equal_to: "кількість сторінок має бути більшою або дорівнювати %{min} (поточна кількість сторінок становить %{pages})"
62
+ pages_not_between: "кількість сторінок має бути від %{min} до %{max} (поточна кількість сторінок становить %{pages})"
63
+ pages_not_equal_to: "кількість сторінок має дорівнювати %{exact} (поточна кількість сторінок - %{pages})"
@@ -12,16 +12,19 @@ vi:
12
12
  file_size_not_greater_than: "kích thước tệp phải lớn hơn %{min} (kích thước hiện tại là %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "kích thước tệp phải lớn hơn hoặc bằng %{min} (kích thước hiện tại là %{file_size})"
14
14
  file_size_not_between: "kích thước tệp phải nằm trong khoảng từ %{min} đến %{max} (kích thước hiện tại là %{file_size})"
15
+ file_size_not_equal_to: "kích thước tệp phải bằng %{exact} (kích thước hiện tại là %{file_size})"
15
16
  total_file_size_not_less_than: "tổng kích thước tệp phải nhỏ hơn %{max} (kích thước hiện tại là %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "tổng kích thước tệp phải nhỏ hơn hoặc bằng %{max} (kích thước hiện tại là %{total_file_size})"
17
18
  total_file_size_not_greater_than: "tổng kích thước tệp phải lớn hơn %{min} (kích thước hiện tại là %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "tổng kích thước tệp phải lớn hơn hoặc bằng %{min} (kích thước hiện tại là %{total_file_size})"
19
20
  total_file_size_not_between: "tổng kích thước tệp phải nằm trong khoảng từ %{min} đến %{max} (kích thước hiện tại là %{total_file_size})"
21
+ total_file_size_not_equal_to: "tổng kích thước tệp phải bằng %{exact} (kích thước hiện tại là %{total_file_size})"
20
22
  duration_not_less_than: "thời lượng phải nhỏ hơn %{max} (thời lượng hiện tại là %{duration})"
21
23
  duration_not_less_than_or_equal_to: "thời lượng phải nhỏ hơn hoặc bằng %{max} (thời lượng hiện tại là %{duration})"
22
24
  duration_not_greater_than: "thời lượng phải lớn hơn %{min} (thời lượng hiện tại là %{duration})"
23
25
  duration_not_greater_than_or_equal_to: "thời lượng phải lớn hơn hoặc bằng %{min} (thời lượng hiện tại là %{duration})"
24
26
  duration_not_between: "thời lượng phải nằm trong khoảng từ %{min} và %{max} (thời lượng hiện tại là %{duration})"
27
+ duration_not_equal_to: "thời lượng phải bằng %{exact} (thời lượng hiện tại là %{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "không có tệp nào được đính kèm (phải có giữa các tệp %{min} và %{max})"
27
30
  one: "chỉ có 1 tệp được đính kèm (phải có giữa các tệp %{min} và %{max})"
@@ -52,3 +55,9 @@ vi:
52
55
  aspect_ratio_not_x_y: "phải là %{authorized_aspect_ratios} (tệp hiện tại là %{width}x%{height}px)"
53
56
  aspect_ratio_invalid: "có tỷ lệ khung hình không hợp lệ (tỷ lệ khung hình hợp lệ là %{authorized_aspect_ratios})"
54
57
  file_not_processable: "không được xác định là tệp phương tiện hợp lệ"
58
+ pages_not_less_than: "số trang phải nhỏ hơn %{max} (số trang hiện tại là %{pages})"
59
+ pages_not_less_than_or_equal_to: "số trang phải nhỏ hơn hoặc bằng %{max} (số trang hiện tại là %{pages})"
60
+ pages_not_greater_than: "số trang phải lớn hơn %{min} (số trang hiện tại là %{pages})"
61
+ pages_not_greater_than_or_equal_to: "số trang phải lớn hơn hoặc bằng %{min} (số trang hiện tại là %{pages})"
62
+ pages_not_between: "số trang phải nằm trong khoảng từ %{min} đến %{max} (số trang hiện tại là %{pages})"
63
+ pages_not_equal_to: "số trang phải bằng %{exact} (số trang hiện tại là %{pages})"
@@ -12,16 +12,19 @@ zh-CN:
12
12
  file_size_not_greater_than: "文件大小必须大于 %{min}(当前大小为 %{file_size})"
13
13
  file_size_not_greater_than_or_equal_to: "文件大小必须大于或等于 %{min}(当前大小为 %{file_size})"
14
14
  file_size_not_between: "文件大小必须介于 %{min} 和 %{max} 之间(当前大小为 %{file_size})"
15
+ file_size_not_equal_to: "文件大小必须等于 %{exact}(当前大小为 %{file_size})"
15
16
  total_file_size_not_less_than: "总文件大小必须小于 %{max}(当前大小为 %{total_file_size})"
16
17
  total_file_size_not_less_than_or_equal_to: "文件总大小必须小于或等于 %{max}(当前大小为 %{total_file_size})"
17
18
  total_file_size_not_greater_than: "总文件大小必须大于 %{min}(当前大小为 %{total_file_size})"
18
19
  total_file_size_not_greater_than_or_equal_to: "文件总大小必须大于或等于 %{min}(当前大小为 %{total_file_size})"
19
20
  total_file_size_not_between: "总文件大小必须介于 %{min} 和 %{max} 之间(当前大小为 %{total_file_size})"
21
+ total_file_size_not_equal_to: "总文件大小必须等于 %{exact}(当前大小为 %{total_file_size})"
20
22
  duration_not_less_than: "持续时间必须小于%{max}(当前持续时间为%{duration})"
21
23
  duration_not_less_than_or_equal_to: "持续时间必须小于或等于%{max}(当前持续时间为%{duration})"
22
24
  duration_not_greater_than: "持续时间必须大于%{min}(当前持续时间为%{duration})"
23
25
  duration_not_greater_than_or_equal_to: "持续时间必须大于或等于%{min}(当前持续时间为%{duration})"
24
26
  duration_not_between: "持续时间必须在%{min}和%{max}之间(当前持续时间为%{duration})"
27
+ duration_not_equal_to: "持续时间必须等于%{exact}(当前持续时间为%{duration})"
25
28
  limit_out_of_range:
26
29
  zero: "未附加文件(必须具有%{min}和%{max}文件之间)"
27
30
  one: "仅附加1个文件(必须具有%{min}和%{max}文件之间)"
@@ -52,3 +55,9 @@ zh-CN:
52
55
  expect_ratio_not_x_y: "必须为 %{authorized_aspect_ratios}(当前文件为 %{width} x%{height} 像素)"
53
56
  expect_ratio_not_in_list: "具有无效的长宽比(有效长宽比为 %{authorized_aspect_ratios})"
54
57
  file_not_processable: "未标识为有效的媒体文件"
58
+ pages_not_less_than: "页数必须小于 %{max}(当前页数为 %{pages})"
59
+ pages_not_less_than_or_equal_to: "页数必须小于或等于 %{max}(当前页数为 %{pages})"
60
+ pages_not_greater_than: "页数必须大于 %{min}(当前页数为 %{pages})"
61
+ pages_not_greater_than_or_equal_to: "页数必须大于或等于 %{min}(当前页数为 %{pages})"
62
+ pages_not_between: "页数必须介于 %{min} 和 %{max} 之间(当前页数为 %{pages})"
63
+ pages_not_equal_to: "页数必须等于 %{exact}(当前页数为%{pages})"
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+
5
+ module ActiveStorageValidations
6
+ # = ActiveStorageValidations PDF \Analyzer
7
+ #
8
+ # Extracts the following from a pdf attachable:
9
+ #
10
+ # * Width (pts) => for the first page only
11
+ # * Height (pts) => for the first page only
12
+ # * Pages (integer) => number of pages in the pdf
13
+ #
14
+ # Example:
15
+ #
16
+ # ActiveStorageValidations::Analyzer::PdfAnalyzer.new(attachable).metadata
17
+ # # => { width: 150, height: 150, pages: 1 }
18
+ #
19
+ # This analyzer requires the {poppler}[https://pdf2image.readthedocs.io/en/latest/installation.html] system library, which is not provided by \Rails.
20
+ class Analyzer::PdfAnalyzer < Analyzer
21
+ def metadata
22
+ read_media do |media|
23
+ {
24
+ width: width,
25
+ height: height,
26
+ pages: pages
27
+ }.compact
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def read_media
34
+ Tempfile.create(binmode: true) do |tempfile|
35
+ begin
36
+ if media(tempfile).present?
37
+ yield media(tempfile)
38
+ else
39
+ logger.info "Skipping pdf file metadata analysis because poppler doesn't support the file"
40
+ {}
41
+ end
42
+ ensure
43
+ tempfile.close
44
+ end
45
+ end
46
+ rescue Errno::ENOENT
47
+ logger.info "Skipping pdf file metadata analysis because poppler isn't installed"
48
+ {}
49
+ end
50
+
51
+ def media_from_path(path)
52
+ instrument(File.basename(pdfinfo_path)) do
53
+ stdout, _stderr, status = Open3.capture3(
54
+ pdfinfo_path,
55
+ path
56
+ )
57
+
58
+ status.success? ? stdout_to_hash(stdout) : nil
59
+ end
60
+ end
61
+
62
+ def stdout_to_hash(stdout)
63
+ stdout.lines.each_with_object({}) do |line, hash|
64
+ key, value = line.strip.split(":", 2)
65
+ hash[normalize_stdout_key(key)] = value.strip if key && value
66
+ end
67
+ end
68
+
69
+ def normalize_stdout_key(key)
70
+ key.strip.underscore.gsub(/\s+/, "_").gsub(/"/, "")
71
+ end
72
+
73
+ def pdfinfo_path
74
+ ActiveStorage.paths[:pdfinfo] || "pdfinfo"
75
+ end
76
+
77
+ def width
78
+ @media["page_size"].scan(/\d+/)[0].to_i
79
+ end
80
+
81
+ def height
82
+ @media["page_size"].scan(/\d+/)[1].to_i
83
+ end
84
+
85
+ def pages
86
+ @media["pages"].to_i
87
+ end
88
+ end
89
+ end
@@ -18,6 +18,7 @@ module ActiveStorageValidations
18
18
  greater_than
19
19
  greater_than_or_equal_to
20
20
  between
21
+ equal_to
21
22
  ].freeze
22
23
 
23
24
  def initialize(*args)
@@ -29,10 +30,14 @@ module ActiveStorageValidations
29
30
 
30
31
  def check_validity!
31
32
  unless AVAILABLE_CHECKS.one? { |argument| options.key?(argument) }
32
- raise ArgumentError, "You must pass either :less_than(_or_equal_to), :greater_than(_or_equal_to), or :between to the validator"
33
+ raise ArgumentError, "You must pass either :less_than(_or_equal_to), :greater_than(_or_equal_to), :between or :equal_to to the validator"
33
34
  end
34
35
  end
35
36
 
37
+ def validate_each(record, attribute, value)
38
+ raise NotImplementedError
39
+ end
40
+
36
41
  private
37
42
 
38
43
  def is_valid?(value, flat_options)
@@ -48,11 +53,14 @@ module ActiveStorageValidations
48
53
  value > flat_options[:greater_than]
49
54
  elsif flat_options[:greater_than_or_equal_to].present?
50
55
  value >= flat_options[:greater_than_or_equal_to]
56
+ elsif flat_options[:equal_to].present?
57
+ value == flat_options[:equal_to]
51
58
  end
52
59
  end
53
60
 
54
61
  def populate_error_options(errors_options, flat_options)
55
62
  errors_options[:min] = format_bound_value(min(flat_options))
63
+ errors_options[:exact] = format_bound_value(exact(flat_options))
56
64
  errors_options[:max] = format_bound_value(max(flat_options))
57
65
  end
58
66
 
@@ -64,6 +72,10 @@ module ActiveStorageValidations
64
72
  flat_options[:between]&.min || flat_options[:greater_than] || flat_options[:greater_than_or_equal_to]
65
73
  end
66
74
 
75
+ def exact(flat_options)
76
+ flat_options[:equal_to]
77
+ end
78
+
67
79
  def max(flat_options)
68
80
  flat_options[:between]&.max || flat_options[:less_than] || flat_options[:less_than_or_equal_to]
69
81
  end
@@ -13,6 +13,7 @@ module ActiveStorageValidations
13
13
  duration_not_greater_than
14
14
  duration_not_greater_than_or_equal_to
15
15
  duration_not_between
16
+ duration_not_equal_to
16
17
  ].freeze
17
18
  METADATA_KEYS = %i[duration].freeze
18
19
 
@@ -58,6 +58,11 @@ module ActiveStorageValidations
58
58
  self
59
59
  end
60
60
 
61
+ def equal_to(value)
62
+ @exact = value
63
+ self
64
+ end
65
+
61
66
  def matches?(subject)
62
67
  @subject = subject.is_a?(Class) ? subject.new : subject
63
68
 
@@ -68,7 +73,8 @@ module ActiveStorageValidations
68
73
  not_lower_than_min? &&
69
74
  higher_than_min? &&
70
75
  lower_than_max? &&
71
- not_higher_than_max?
76
+ not_higher_than_max? &&
77
+ equal_to_exact?
72
78
  end
73
79
 
74
80
  protected
@@ -103,6 +109,10 @@ module ActiveStorageValidations
103
109
  @max.nil? || @max == Float::INFINITY || !passes_validation_with_value(@max + 1)
104
110
  end
105
111
 
112
+ def equal_to_exact?
113
+ @exact.nil? || passes_validation_with_value(@exact)
114
+ end
115
+
106
116
  def smallest_measurement
107
117
  raise NotImplementedError
108
118
  end