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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a82f321d71985caf479d40c9546bc6b0c216ba97670d200e775be3274cf9a35c
4
- data.tar.gz: 3a80b0ad6db919d7968a2162214004240d152648ee2ac8c4c4eafe1119834c1c
3
+ metadata.gz: 52bbd6249bbadd7549ccd7daf17673e98ccfd757b15ec954b67c5d7ce3395c84
4
+ data.tar.gz: cf3664efb821cd7fe60b0536e0d394f900af6fb128161ab13d62d373b2018013
5
5
  SHA512:
6
- metadata.gz: c3d19095f455bb32b649c4ab0bfc7ae50d2d29eae69d5b3a593d6dd556de9ba7c527eb4afe9ec8032638adec23f664d200bcfab75cd726f51be97492266fc1b0
7
- data.tar.gz: 6ab99b207ef0399354c56d499d004cd287c22a56fd1648a5c2f948eace0050e00d13d12e3bb2ca38ba730edf2539b3843637383a8d3c8dc6424daa91f764164c
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
- 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 valiation method.
3
+ [![MiniTest](https://github.com/igorkasyanchuk/active_storage_validations/workflows/MiniTest/badge.svg)](https://github.com/igorkasyanchuk/active_storage_validations/actions)
4
+ [![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
5
+ [![https://www.patreon.com/igorkasyanchuk](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/patron.svg?raw=true)](https://www.patreon.com/igorkasyanchuk)
4
6
 
5
- This gems doing it for you. Just use `attached: true` or `content_type: 'image/png'` validation.
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
- [![Build Status](https://travis-ci.org/igorkasyanchuk/active_storage_validations.svg?branch=master)](https://travis-ci.org/igorkasyanchuk/active_storage_validations)
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 `Mime::Type`.
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 # Mime[:png].to_s => 'image/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
- To play with app `cd test/dummy` and `rails s -b 0.0.0.0` (before `rails db:migrate`).
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/)
@@ -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 von %{file_size} ist außerhalb des erlaubten Bereichs"
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 nicht ein gültigen Bild"
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: "Breite ist nicht zwischen %{min} und %{max} Pixel enthalten"
11
- dimension_height_inclusion: "Höhe ist nicht zwischen %{min} und %{max} Pixel enthalten"
12
- dimension_width_greater_than_or_equal_to: "Breite muss größer oder gleich %{length} Pixel sein"
13
- dimension_height_greater_than_or_equal_to: "Höhe muss größer oder gleich %{length} Pixel sein"
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: "Breite muss genau %{length} Pixel sein"
17
- dimension_height_equal_to: "Höhe muss genau %{length} Pixel sein"
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"
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"
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ı"
@@ -1,22 +1,22 @@
1
1
  uk:
2
2
  errors:
3
3
  messages:
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: "має невідоме співвідношення сторін"
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::VERSION::MAJOR >= 6
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
- record.errors.add(attribute, :blank)
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
- (Array.wrap(options[:with]) + Array.wrap(options[:in])).compact.map do |type|
24
- Mime[type] || type
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
- if options[:with].is_a?(Regexp)
40
- options[:with].match?(content_type(file).to_s)
41
- else
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::VERSION::MAJOR >= 6
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, *attrs)
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, *attrs)
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.class
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
- instance = @subject.new
36
- instance.public_send(@attribute_name).attach(attachable)
37
- instance.validate
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
- instance = @subject.new
43
- instance.validate
44
- instance.errors.details[@attribute_name].include?(error: :blank)
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 || (Mime::LOOKUP.keys - allowed_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
- width_smaller_than_min? && width_larger_than_min? && width_smaller_than_max? && width_larger_than_max? && width_equals? &&
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
- @subject.errors.details[@attribute_name].all? { |error| error[:error].to_s.exclude?("dimension_#{check}") }
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::VERSION::MAJOR >= 6
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 = is_string ? ActiveStorage::Blob.find_signed(file) : file
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
- record.errors.add(attribute, :file_size_out_of_range, errors_options)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageValidations
4
- VERSION = '0.8.8'
4
+ VERSION = '0.9.6'
5
5
  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.8.8
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: 2020-03-21 00:00:00.000000000 Z
11
+ date: 2021-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
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: mini_magick
28
+ name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 4.9.5
34
- type: :development
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: 4.9.5
40
+ version: 5.2.0
41
41
  - !ruby/object:Gem::Dependency
42
- name: pry
42
+ name: activestorage
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
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: '0'
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: rubocop
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: sqlite3
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: coffee-rails
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.0.6
198
+ rubygems_version: 3.1.4
151
199
  signing_key:
152
200
  specification_version: 4
153
201
  summary: Validations for Active Storage