Skip to content

Commit

Permalink
[Validator] Replace processable_image validator to processable_file (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Mth0158 committed Dec 29, 2024
1 parent 192a2bc commit 12bea24
Show file tree
Hide file tree
Showing 58 changed files with 195 additions and 174 deletions.
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Once you have installed the gem, you need to add the gem I18n error messages to

### Using image metadata validators

Optionally, to use the image metadata validators (`dimension`, `aspect_ratio` and `processable_image`), you will have to add one of the corresponding gems:
Optionally, to use the image metadata validators (`dimension`, `aspect_ratio` and `processable_file`), you will have to add one of the corresponding gems:

```ruby
gem 'mini_magick', '>= 4.9.5'
Expand All @@ -69,7 +69,7 @@ Plus, you have to be sure to have the corresponding command-line tool installed

### Using video and audio metadata validators

To use the video and audio metadata validators (`dimension`, `aspect_ratio` 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).
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).

## Validators

Expand All @@ -81,9 +81,8 @@ List of validators:
- [Total size](#total-size): validates total file size for several files
- [Dimension](#dimension): validates image / video dimensions
- [Aspect ratio](#aspect-ratio): validates image / video aspect ratio
- [Processable image](#processable-image): validates if an image can be processed
- [Processable file](#processable-file): validates if a file can be processed
🚧 TODO: Add `duration` validator
🚧 TODO: Update `processable_image` validator to `processable`

**Proc usage**

Expand Down Expand Up @@ -507,13 +506,13 @@ The `aspect_ratio` validator error messages expose 4 values that you can use:

---

### Processable image
### Processable file

Validates if the attached files can be processed by MiniMagick or Vips.
Validates if the attached files can be processed by MiniMagick or Vips (image) or ffmpeg (video/audio).

#### Options

The `processable_image` validator has no options.
The `processable_file` validator has no options.

#### Examples

Expand All @@ -522,7 +521,7 @@ Use it like this:
class User < ApplicationRecord
has_one_attached :avatar
validates :avatar, processable_image: true # restricts the file to be processable by MiniMagick or Vips
validates :avatar, processable_file: true # ensures that the file is processable by MiniMagick or Vips (image) or ffmpeg (video/audio)
end
```

Expand All @@ -532,10 +531,10 @@ end
en:
errors:
messages:
image_not_processable: "is not a valid image"
file_not_processable: "is not identified as a valid media file"
```

The `processable_image` validator error messages expose 1 value that you can use:
The `processable_file` validator error messages expose 1 value that you can use:
- `filename` containing the current filename in error

---
Expand All @@ -547,6 +546,7 @@ If you are upgrading from 1.x to 2.x, you will be pleased to note that a lot of
Added features:
- `dimension` validator now supports videos
- `aspect_ratio` validator now supports videos
- `processable_image` validator is now `processable_file` validator and supports image/video/audio
- All error messages have been given an upgrade and new variables that you can use

But this major version bump also comes with some breaking changes. Below are the main breaking changes you need to be aware of:
Expand All @@ -556,6 +556,7 @@ But this major version bump also comes with some breaking changes. Below are the
- `limit` validator keys have been totally reworked
- `dimension` validator keys have been totally reworked
- `content_type` validator keys have been totally reworked
- `processable_image` validator keys have been totally reworked
- Some keys have been changed:
- `image_metadata_missing` has been replaced by `media_metadata_missing`
- `aspect_ratio_is_not` has been replaced by `aspect_ratio_not_x_y`
Expand All @@ -571,6 +572,10 @@ But this major version bump also comes with some breaking changes. Below are the
- This might break some cases when you had for example `content_type: ['image/png', 'image/jpg']`, because `image/jpg` is not a valid content type, it should be replaced by `image/jpeg`.
- An `ArgumentError` is now raised if `image/jpg` is used to make it easier to fix. You should now only use `image/jpeg`.

- `processable_image` validator
- The validator has been replaced by `processable_file` validator, be sure to replace `processable_image: true` to `processable_file: true`
- The associated matcher has also been updated accordingly, be sure to replace `validate_processable_image_of` to `validate_processable_file_of`

🚧 TODO: Add more details about the other changes when implemented


Expand Down Expand Up @@ -624,7 +629,7 @@ en:
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
image_not_processable: "is not a valid image"
file_not_processable: "is not identified as a valid media file"
```


Expand Down Expand Up @@ -662,8 +667,8 @@ describe User do
# attached
it { is_expected.to validate_attached_of(:avatar) }
# processable_image
it { is_expected.to validate_processable_image_of(:avatar) }
# processable_file
it { is_expected.to validate_processable_file_of(:avatar) }
# limit
# #min, #max
Expand Down
2 changes: 1 addition & 1 deletion config/locales/da.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ da:
aspect_ratio_not_landscape: "skal være landskab (nuværende fil er %{width}x%{height}px)"
aspect_ratio_not_x_y: "skal være %{authorized_aspect_ratios} (nuværende fil er %{width}x%{height}px)"
aspect_ratio_invalid: "har et ugyldigt aspektforhold (gyldige aspektforhold er %{authorized_aspect_ratios})"
image_not_processable: "er ikke et gyldigt billede"
file_not_processable: "identificeres ikke som en gyldig mediefil"
2 changes: 1 addition & 1 deletion config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ de:
aspect_ratio_not_landscape: "muss landschaftlich sein (aktuelle Datei ist %{width}x%{height}px)"
aspect_ratio_not_x_y: "muss %{authorized_aspect_ratios} sein (aktuelle Datei ist %{width}x%{height}px)"
aspect_ratio_invalid: "hat ein ungültiges Seitenverhältnis (gültige Seitenverhältnisse sind %{authorized_aspect_ratios})"
image_not_processable: "ist kein gültiges Bild"
file_not_processable: "wird nicht als gültige Mediendatei identifiziert"
2 changes: 1 addition & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ en:
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
image_not_processable: "is not a valid image"
file_not_processable: "is not identified as a valid media file"
2 changes: 1 addition & 1 deletion config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ es:
aspect_ratio_not_landscape: "debe ser paisaje (el archivo actual es %{width}x%{height}px)"
aspect_ratio_not_x_y: "debe ser %{authorized_aspect_ratios} (el archivo actual es %{width}x%{height}px)"
aspect_ratio_invalid: "tiene una relación de aspecto inválida (las relaciones de aspecto válidas son %{authorized_aspect_ratios})"
image_not_processable: "no es una imagen válida"
file_not_processable: "no se identifica como un archivo multimedia válido"
2 changes: 1 addition & 1 deletion config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ fr:
aspect_ratio_not_landscape: "doit être paysage (le fichier actuel est %{width}x%{height}px)"
aspect_ratio_not_x_y: "doit être %{authorized_aspect_ratios} (le fichier actuel est %{width}x%{height}px)"
aspect_ratio_invalid: "a un rapport d'aspect invalide (les rapports d'aspect valides sont %{authorized_aspect_ratios})"
image_not_processable: "n'est pas une image valide"
file_not_processable: "n'est pas identifié comme un fichier média valide"
2 changes: 1 addition & 1 deletion config/locales/it.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ it:
aspect_ratio_not_landscape: "deve essere orizzontale (il file corrente è %{width}x%{height}px)"
aspect_ratio_not_x_y: "deve essere %{authorized_aspect_ratios} (il file corrente è %{width}x%{height}px)"
aspect_ratio_invalid: "ha un formato non valido (i rapporti di aspetto validi sono %{authorized_aspect_ratios})"
image_not_processable: "non è un'immagine valida"
file_not_processable: "non è identificato come file multimediale valido"
2 changes: 1 addition & 1 deletion config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ ja:
aspect_ratio_not_landscape: "は横長である必要があります(現在のファイルは%{width}x%{height})"
aspect_ratio_not_x_y: "は%{authorized_aspect_ratios}である必要があります(現在のファイルは%{width}x%{height})"
aspect_ratio_invalid: "は無効なアスペクト比です(有効なアスペクト比は%{authorized_aspect_ratios}です)"
image_not_processable: "は不正な画像です"
file_not_processable: "有効なメディアファイルとして識別されない"
2 changes: 1 addition & 1 deletion config/locales/nl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ nl:
aspect_ratio_not_landscape: "moet landschap zijn (huidig bestand is %{width}x%{height}px)"
aspect_ratio_not_x_y: "moet %{authorized_aspect_ratios} zijn (huidig bestand is %{width}x%{height}px)"
aspect_ratio_invalid: "heeft een ongeldige beeldverhouding (geldige beeldverhoudingen zijn %{authorized_aspect_ratios})"
image_not_processable: "is geen geldige afbeelding"
file_not_processable: "wordt niet geïdentificeerd als een geldig mediabestand"
3 changes: 1 addition & 2 deletions config/locales/pl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,4 @@ pl:
aspect_ratio_not_landscape: "musi być krajobrazem (bieżący plik to %{width}x%{height}px)"
aspect_ratio_not_x_y: "musi być %{authorized_aspect_ratios} (bieżący plik to %{width}x%{height}px)"
aspect_ratio_invalid: "ma nieprawidłowy współczynnik kształtu (ważne współczynniki kształtu wynoszą %{authorized_aspect_ratios})"
image_not_processable: "nie jest prawidłowym obrazem"

file_not_processable: "nie jest identyfikowany jako prawidłowy plik multimedialny"
2 changes: 1 addition & 1 deletion config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ pt-BR:
aspect_ratio_not_landscape: "deve ser paisagem (o ficheiro actual é %{width}x%{height}px)"
aspect_ratio_not_x_y: "deve ser %{authorized_aspect_ratios} (o ficheiro actual é %{width}x%{height}px)"
aspect_ratio_invalid: "tem uma proporção inválida (as proporções válidas são %{authorized_aspect_ratios})"
image_not_processable: "não é uma imagem válida"
file_not_processable: "não é identificado como um arquivo de mídia válido"
2 changes: 1 addition & 1 deletion config/locales/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ ru:
aspect_ratio_not_landscape: "должен быть ландшафт (текущий файл %{width}x%{height} пикселей)"
aspect_ratio_not_x_y: "должно быть %{authorized_aspect_ratios} (текущий файл %{width}x%{height} пикселей)"
aspect_ratio_invalid: "имеет недействительное соотношение сторон (действительные соотношения сторон %{authorized_aspect_ratios})"
image_not_processable: "не является допустимым изображением"
file_not_processable: "не идентифицируется как действительный медиафайл"
2 changes: 1 addition & 1 deletion config/locales/sv.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ sv:
aspect_ratio_not_landscape: "måste vara landskap (nuvarande fil är %{width}x%{height} pixlar)"
aspect_ratio_not_x_y: "måste vara% { authorized_aspect_ratios } (nuvarande fil är %{width}x%{height} pixlar)"
aspect_ratio_invalid: "har ett ogiltigt bildförhållande (giltiga bildförhållanden är %{förväntat_aspect_ratios})"
image_not_processable: "är inte en giltig bild"
file_not_processable: "identifieras inte som en giltig mediefil"
2 changes: 1 addition & 1 deletion config/locales/tr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ tr:
aspect_ratio_not_landscape: "yatay olmalıdır (geçerli dosya %{width}x%{height}px)"
aspect_ratio_not_x_y: "%{authorized_aspect_ratios} olmalıdır (geçerli dosya %{width}x%{height}px)"
aspect_ratio_invalid: "geçersiz bir en boy oranına sahiptir (geçerli en boy oranları %{authorized_aspect_ratios})"
image_not_processable: "geçerli bir imaj değil"
file_not_processable: "geçerli bir medya dosyası olarak tanımlanmadı"
2 changes: 1 addition & 1 deletion config/locales/uk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ uk:
aspect_ratio_not_landscape: "повинен бути пейзажним (поточний файл %{width}x%{height} пікселям)"
aspect_ratio_not_x_y: "повинен бути %{authorized_aspect_ratios} (поточний файл становить %{width}x%{height} пікселям)"
aspect_ratio_invalid: "має недійсне співвідношення сторін (дійсні співвідношення сторін %{authorized_aspect_ratios})"
image_not_processable: "не є допустимим зображенням"
file_not_processable: "не ідентифікується як дійсний медіа-файл"
3 changes: 1 addition & 2 deletions config/locales/vi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,4 @@ vi:
aspect_ratio_not_landscape: "phải là ngang (tệp hiện tại là %{width}x%{height}px)"
aspect_ratio_not_x_y: "phải là %{authorized_aspect_ratios} (tệp hiện tại là %{width}x%{height}px)"
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})"
image_not_processable: "không phải là ảnh"

file_not_processable: "không được xác định là tệp phương tiện hợp lệ"
2 changes: 1 addition & 1 deletion config/locales/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ zh-CN:
aspect_ratio_not_landscape: "必须是横向(当前文件为 %{width} x%{height} 像素)"
expect_ratio_not_x_y: "必须为 %{authorized_aspect_ratios}(当前文件为 %{width} x%{height} 像素)"
expect_ratio_not_in_list: "具有无效的长宽比(有效长宽比为 %{authorized_aspect_ratios})"
image_not_processable: "不是有效的图像"
file_not_processable: "未标识为有效的媒体文件"
2 changes: 1 addition & 1 deletion lib/active_storage_validations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
require 'active_storage_validations/limit_validator'
require 'active_storage_validations/dimension_validator'
require 'active_storage_validations/aspect_ratio_validator'
require 'active_storage_validations/processable_image_validator'
require 'active_storage_validations/processable_file_validator'
require 'active_storage_validations/size_validator'
require 'active_storage_validations/total_size_validator'

Expand Down
2 changes: 1 addition & 1 deletion lib/active_storage_validations/matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require 'active_storage_validations/matchers/aspect_ratio_validator_matcher'
require 'active_storage_validations/matchers/attached_validator_matcher'
require 'active_storage_validations/matchers/processable_image_validator_matcher'
require 'active_storage_validations/matchers/processable_file_validator_matcher'
require 'active_storage_validations/matchers/limit_validator_matcher'
require 'active_storage_validations/matchers/content_type_validator_matcher'
require 'active_storage_validations/matchers/dimension_validator_matcher'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

module ActiveStorageValidations
module Matchers
def validate_processable_image_of(name)
ProcessableImageValidatorMatcher.new(name)
def validate_processable_file_of(name)
ProcessableFileValidatorMatcher.new(name)
end

class ProcessableImageValidatorMatcher
class ProcessableFileValidatorMatcher
include ASVActiveStorageable
include ASVAllowBlankable
include ASVAttachable
Expand Down Expand Up @@ -46,7 +46,7 @@ def matches?(subject)
is_context_valid? &&
is_custom_message_valid? &&
is_valid_when_image_processable? &&
is_invalid_when_image_not_processable?
is_invalid_when_file_not_processable?
end

private
Expand All @@ -58,7 +58,7 @@ def is_valid_when_image_processable?
is_valid?
end

def is_invalid_when_image_not_processable?
def is_invalid_when_file_not_processable?
attach_file(not_processable_image)
validate
detach_file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
require_relative 'shared/asv_symbolizable'

module ActiveStorageValidations
class ProcessableImageValidator < ActiveModel::EachValidator # :nodoc
class ProcessableFileValidator < ActiveModel::EachValidator # :nodoc
include ASVActiveStorageable
include ASVAnalyzable
include ASVAttachable
include ASVErrorable
include ASVSymbolizable

ERROR_TYPES = %i[
image_not_processable
file_not_processable
].freeze

def validate_each(record, attribute, _value)
Expand Down
2 changes: 1 addition & 1 deletion test/active_storage_validations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ class ActiveStorageValidations::Test < ActiveSupport::TestCase
e.proc_image.attach(image_1920x1080_file)
e.another_image.attach(tar_file_with_image_content_type)
assert !e.valid?
assert_equal ["Another image is not a valid image"], e.errors.full_messages
assert_equal ["Another image is not identified as a valid media file"], e.errors.full_messages

e = OnlyImage.new
e.image.attach(image_1920x1080_file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ class Integration::Validator::ZeroByteImage < ApplicationRecord
has_one_attached :zero_byte_image
validates :zero_byte_image, attached: true,
content_type: :png,
processable_image: true
processable_file: true
end
4 changes: 2 additions & 2 deletions test/dummy/app/models/only_image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ class OnlyImage < ApplicationRecord
validates :proc_image, dimension: { width: { min: -> (record) {100}, max: -> (record) {2000} }, height: { min: -> (record) {100}, max: -> (record) {1500} } },
aspect_ratio: -> (record) {:is_16_9},
content_type: -> (record) {['image/png', 'image/jpeg']}
validates :another_image, processable_image: true
validates :any_image, processable_image: false
validates :another_image, processable_file: true
validates :any_image, processable_file: false
end
5 changes: 5 additions & 0 deletions test/dummy/app/models/processable_file.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module ProcessableFile
def self.table_name_prefix
'processable_file_'
end
end
46 changes: 46 additions & 0 deletions test/dummy/app/models/processable_file/matcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: processable_file_matchers
#
# title :string
# id :integer not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
#

class ProcessableFile::Matcher < ApplicationRecord
include Validatable

has_one_attached :custom_matcher
validates :custom_matcher, processable_file: true

has_one_attached :processable
validates :processable, processable_file: true

has_one_attached :with_message
validates :with_message, processable_file: { message: 'Custom message' }

has_one_attached :with_context_symbol
validates :with_context_symbol, processable_file: true, on: :update
has_one_attached :with_context_array
validates :with_context_array, processable_file: true, on: %i[update custom]
has_one_attached :with_several_validators_and_contexts
validates :with_several_validators_and_contexts, processable_file: true, on: :update
validates :with_several_validators_and_contexts, processable_file: true, on: :custom

has_one_attached :as_instance
validates :as_instance, processable_file: true

has_one_attached :validatable_different_error_messages
validates :validatable_different_error_messages, processable_file: { message: 'Custom message 1' }, if: :title_is_quo_vadis?
validates :validatable_different_error_messages, processable_file: { message: 'Custom message 2' }, if: :title_is_american_psycho?

has_one_attached :failure_message
validates :failure_message, processable_file: true
has_one_attached :failure_message_when_negated
validates :failure_message_when_negated, processable_file: true

has_one_attached :not_processable
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module ProcessableImage
module ProcessableFile
module Validator
def self.table_name_prefix
'processable_image_validator_'
'processable_file_validator_'
end
end
end
Loading

0 comments on commit 12bea24

Please sign in to comment.