Skip to content

Commit 201e404

Browse files
committed
Merge branch 'master' into 364-active_storage_validations-200-causing-stack-level-too-deep
2 parents 351c781 + f36a326 commit 201e404

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+889
-168
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,15 @@ jobs:
3434
- rails_7_1
3535
- rails_7_2
3636
- rails_8_0
37+
- rails_next
3738
image_processor:
3839
- vips
3940
- mini_magick
4041
exclude:
4142
- ruby: '3.1'
4243
gemfile: rails_8_0
44+
- ruby: '3.1'
45+
gemfile: rails_next
4346
- ruby: '3.3'
4447
gemfile: rails_7_0
4548
include:

CHANGES.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
- 2.0.4
2+
- Fix issue when updating a child record through a parent (like: parent_model.update(child_attributes: { image: file })) for Rails >= 8.0.2 (https://github.com/igorkasyanchuk/active_storage_validations/pull/378)
3+
4+
- 2.0.3
5+
- Allow to pass an Array, a splatted Array, or a single string for allowing / rejecting content_type matcher methods (https://github.com/igorkasyanchuk/active_storage_validations/pull/372)
6+
- Fix issue when an attachment was missing on a blob (https://github.com/igorkasyanchuk/active_storage_validations/pull/373)
7+
18
- 2.0.2
29
- Fix undesirable mutation of Marcel::TYPE_EXTS (https://github.com/igorkasyanchuk/active_storage_validations/issues/356)
3-
- Fix gem loading issue with Marcel custo initialisers (https://github.com/igorkasyanchuk/active_storage_validations/issues/355)
10+
- Fix gem loading issue with Marcel custom initialisers (https://github.com/igorkasyanchuk/active_storage_validations/issues/355)
411

512
- 2.0.1
613
- Fix for invalid content type validation ([PR #347](https://github.com/igorkasyanchuk/active_storage_validations/pull/347))

Gemfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ gemspec
2020
# gem "nokogiri", "~> 1.16", ">= 1.16.7"
2121

2222
group :development, :test do
23-
# To use a debugger:
24-
# gem 'byebug'
23+
# To use debugger:
24+
# gem "debug", "~> 1.10", ">= 1.10.0"
2525

2626
# To test S3 services
2727
# gem "aws-sdk-s3", require: false

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
active_storage_validations (2.0.2)
4+
active_storage_validations (2.0.3)
55
activejob (>= 6.1.4)
66
activemodel (>= 6.1.4)
77
activestorage (>= 6.1.4)

README.md

Lines changed: 15 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
[![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
88
[![https://www.patreon.com/igorkasyanchuk](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/patron.svg?raw=true)](https://www.patreon.com/igorkasyanchuk)
99

10+
[!["Buy Me A Coffee"](https://github.com/igorkasyanchuk/get-smart/blob/main/docs/snapshot-bmc-button-small.png?raw=true)](https://buymeacoffee.com/igorkasyanchuk)
1011

1112
Active Storage Validations is a gem that allows you to add validations for Active Storage attributes.
1213

@@ -53,7 +54,7 @@ $ bundle
5354

5455
### Error messages (I18n)
5556

56-
Once you have installed the gem, you need to add the gem I18n error messages to your app. See [Internationalization (I18n)](#internationalization-i18n) section for more details.
57+
Once you have installed the gem, I18n error messages will be added automatically to your app. See [Internationalization (I18n)](#internationalization-i18n) section for more details.
5758

5859
### Using image metadata validators
5960

@@ -71,6 +72,8 @@ Plus, you have to be sure to have the corresponding command-line tool installed
7172

7273
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).
7374

75+
If you want some inspiration about how to add `imagemagick`, `libvips` or `ffmpeg` to your docker image, you can check how we do it for the gem CI (https://github.com/igorkasyanchuk/active_storage_validations/blob/master/.github/workflows/main.yml)
76+
7477
### Using content type spoofing protection validator option
7578

7679
To use the `spoofing_protection` option with the `content_type` validator, you only need to have the UNIX `file` command on your system.
@@ -248,7 +251,7 @@ If you choose to use a content_type 'shorthand' (like `png`), note that it will
248251
Marcel::MimeType.extend "application/ino", extensions: %w(ino), parents: "text/plain" # Registering arduino INO files
249252
```
250253

251-
Be sure to at least include one the the `extensions`, `parents` or `magic` option, otherwise the content type will not be registered.
254+
Be sure to at least include one the `extensions`, `parents` or `magic` option, otherwise the content type will not be registered.
252255

253256
#### Content type spoofing protection
254257

@@ -656,65 +659,11 @@ But this major version bump also comes with some breaking changes. Below are the
656659

657660
## Internationalization (I18n)
658661

659-
Active Storage Validations uses I18n for error messages. Add these keys in your translation files to make them available:
662+
Active Storage Validations uses I18n for error messages. The error messages are automatically loaded in your Rails app if your language translations are present in the gem.
660663

661-
```yml
662-
en:
663-
errors:
664-
messages:
665-
content_type_invalid:
666-
one: "has an invalid content type (authorized content type is %{authorized_human_content_types})"
667-
other: "has an invalid content type (authorized content types are %{authorized_human_content_types})"
668-
content_type_spoofed:
669-
one: "has a content type that is not equivalent to the one that is detected through its content (authorized content type is %{authorized_human_content_types})"
670-
other: "has a content type that is not equivalent to the one that is detected through its content (authorized content types are %{authorized_human_content_types})"
671-
file_size_not_less_than: "file size must be less than %{max} (current size is %{file_size})"
672-
file_size_not_less_than_or_equal_to: "file size must be less than or equal to %{max} (current size is %{file_size})"
673-
file_size_not_greater_than: "file size must be greater than %{min} (current size is %{file_size})"
674-
file_size_not_greater_than_or_equal_to: "file size must be greater than or equal to %{min} (current size is %{file_size})"
675-
file_size_not_between: "file size must be between %{min} and %{max} (current size is %{file_size})"
676-
total_file_size_not_less_than: "total file size must be less than %{max} (current size is %{total_file_size})"
677-
total_file_size_not_less_than_or_equal_to: "total file size must be less than or equal to %{max} (current size is %{total_file_size})"
678-
total_file_size_not_greater_than: "total file size must be greater than %{min} (current size is %{total_file_size})"
679-
total_file_size_not_greater_than_or_equal_to: "total file size must be greater than or equal to %{min} (current size is %{total_file_size})"
680-
total_file_size_not_between: "total file size must be between %{min} and %{max} (current size is %{total_file_size})"
681-
duration_not_less_than: "duration must be less than %{max} (current duration is %{duration})"
682-
duration_not_less_than_or_equal_to: "duration must be less than or equal to %{max} (current duration is %{duration})"
683-
duration_not_greater_than: "duration must be greater than %{min} (current duration is %{duration})"
684-
duration_not_greater_than_or_equal_to: "duration must be greater than or equal to %{min} (current duration is %{duration})"
685-
duration_not_between: "duration must be between %{min} and %{max} (current duration is %{duration})"
686-
limit_out_of_range:
687-
zero: "no files attached (must have between %{min} and %{max} files)"
688-
one: "only 1 file attached (must have between %{min} and %{max} files)"
689-
other: "total number of files must be between %{min} and %{max} files (there are %{count} files attached)"
690-
limit_min_not_reached:
691-
zero: "no files attached (must have at least %{min} files)"
692-
one: "only 1 file attached (must have at least %{min} files)"
693-
other: "%{count} files attached (must have at least %{min} files)"
694-
limit_max_exceeded:
695-
zero: "no files attached (maximum is %{max} files)"
696-
one: "too many files attached (maximum is %{max} files, got %{count})"
697-
other: "too many files attached (maximum is %{max} files, got %{count})"
698-
media_metadata_missing: "is not a valid media file"
699-
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixel"
700-
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixel"
701-
dimension_width_not_included_in: "width is not included between %{min} and %{max} pixel"
702-
dimension_height_not_included_in: "height is not included between %{min} and %{max} pixel"
703-
dimension_width_not_greater_than_or_equal_to: "width must be greater than or equal to %{length} pixel"
704-
dimension_height_not_greater_than_or_equal_to: "height must be greater than or equal to %{length} pixel"
705-
dimension_width_not_less_than_or_equal_to: "width must be less than or equal to %{length} pixel"
706-
dimension_height_not_less_than_or_equal_to: "height must be less than or equal to %{length} pixel"
707-
dimension_width_not_equal_to: "width must be equal to %{length} pixel"
708-
dimension_height_not_equal_to: "height must be equal to %{length} pixel"
709-
aspect_ratio_not_square: "must be square (current file is %{width}x%{height}px)"
710-
aspect_ratio_not_portrait: "must be portrait (current file is %{width}x%{height}px)"
711-
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
712-
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
713-
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
714-
file_not_processable: "is not identified as a valid media file"
715-
```
664+
Translation files are available [here](https://github.com/igorkasyanchuk/active_storage_validations/tree/master/config/locales). We currently have translations for `da`, `de`, `en`, `en-GB`, `es`, `fr`, `it`, `ja`, `nl`, `pl`, `pt-BR`, `ru`, `sv`, `tr`, `uk`, `vi` and `zh-CN`. Feel free to drop a PR to add your language ✌️.
716665

717-
Other translation files are available [here](https://github.com/igorkasyanchuk/active_storage_validations/tree/master/config/locales).
666+
If you wish to customize the error messages, just copy, paste and update the translation files into your application locales.
718667

719668
## Test matchers
720669

@@ -760,8 +709,8 @@ describe User do
760709
761710
# content_type:
762711
# #allowing, #rejecting
763-
it { is_expected.to validate_content_type_of(:avatar).allowing('image/png', 'image/gif') }
764-
it { is_expected.to validate_content_type_of(:avatar).rejecting('text/plain', 'text/xml') }
712+
it { is_expected.to validate_content_type_of(:avatar).allowing('image/png', 'image/gif') } # possible to use an Array or *splatted array
713+
it { is_expected.to validate_content_type_of(:avatar).rejecting('text/plain', 'text/xml') } # possible to use an Array or *splatted array
765714
766715
# dimension:
767716
# #width, #height, #width_min, #height_min, #width_max, #height_max, #width_between, #height_between
@@ -853,6 +802,7 @@ To run the gem tests, launch the following commands in the root folder of gem re
853802
* `BUNDLE_GEMFILE=gemfiles/rails_7_1.gemfile bundle exec rake test` to run for Rails 7.1
854803
* `BUNDLE_GEMFILE=gemfiles/rails_7_2.gemfile bundle exec rake test` to run for Rails 7.2
855804
* `BUNDLE_GEMFILE=gemfiles/rails_8_0.gemfile bundle exec rake test` to run for Rails 8.0
805+
* `BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test` to run for Rails main
856806

857807
Snippet to run in console:
858808

@@ -862,11 +812,13 @@ BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle
862812
BUNDLE_GEMFILE=gemfiles/rails_7_1.gemfile bundle
863813
BUNDLE_GEMFILE=gemfiles/rails_7_2.gemfile bundle
864814
BUNDLE_GEMFILE=gemfiles/rails_8_0.gemfile bundle
815+
BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle
865816
BUNDLE_GEMFILE=gemfiles/rails_6_1_4.gemfile bundle exec rake test
866817
BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle exec rake test
867818
BUNDLE_GEMFILE=gemfiles/rails_7_1.gemfile bundle exec rake test
868819
BUNDLE_GEMFILE=gemfiles/rails_7_2.gemfile bundle exec rake test
869820
BUNDLE_GEMFILE=gemfiles/rails_8_0.gemfile bundle exec rake test
821+
BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test
870822
```
871823

872824
Tips:
@@ -890,3 +842,5 @@ The gem is available as open source under the terms of the [MIT License](https:/
890842

891843
[<img src="https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true"
892844
/>](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=active_storage_validations)
845+
846+
[!["Buy Me A Coffee"](https://github.com/igorkasyanchuk/get-smart/blob/main/docs/snapshot-bmc-button.png?raw=true)](https://buymeacoffee.com/igorkasyanchuk)

config/locales/da.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ da:
3434
zero: "ingen filer vedhæftet (maks. er %{max} filer)"
3535
one: "for mange vedhæftede filer (maks. er %{max} filer, fik %{count})"
3636
other: "for mange vedhæftede filer (maks. er %{max} filer, fik %{count})"
37+
attachment_missing: "har ingen vedhæftet fil"
3738
media_metadata_missing: "er ikke en gyldig mediefil"
3839
dimension_min_not_included_in: "skal være større end eller lig med %{width} x %{height} pixel"
3940
dimension_max_not_included_in: "skal være mindre end eller lig med %{width} x %{height} pixel"

config/locales/de.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ de:
3434
zero: "Keine Dateien angehängt (maximal %{max} Dateien)"
3535
one: "zu viele angehängte Dateien (maximal %{max} Dateien, %{count})"
3636
other: "Zu viele angehängte Dateien (maximal %{max} Dateien, %{count})"
37+
attachment_missing: "hat keine angehängte Datei"
3738
media_metadata_missing: "ist keine gültige Mediendatei"
3839
dimension_min_not_included_in: "muss größer oder gleich %{width} x %{height} Pixel sein"
3940
dimension_max_not_included_in: "muss kleiner oder gleich %{width} x %{height} Pixel sein"

config/locales/en-GB.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
en-GB:
2+
errors:
3+
messages:
4+
content_type_invalid:
5+
one: "has an invalid content type (authorized content type is %{authorized_human_content_types})"
6+
other: "has an invalid content type (authorized content types are %{authorized_human_content_types})"
7+
content_type_spoofed:
8+
one: "has a content type that is not equivalent to the one that is detected through its content (authorized content type is %{authorized_human_content_types})"
9+
other: "has a content type that is not equivalent to the one that is detected through its content (authorized content types are %{authorized_human_content_types})"
10+
file_size_not_less_than: "file size must be less than %{max} (current size is %{file_size})"
11+
file_size_not_less_than_or_equal_to: "file size must be less than or equal to %{max} (current size is %{file_size})"
12+
file_size_not_greater_than: "file size must be greater than %{min} (current size is %{file_size})"
13+
file_size_not_greater_than_or_equal_to: "file size must be greater than or equal to %{min} (current size is %{file_size})"
14+
file_size_not_between: "file size must be between %{min} and %{max} (current size is %{file_size})"
15+
total_file_size_not_less_than: "total file size must be less than %{max} (current size is %{total_file_size})"
16+
total_file_size_not_less_than_or_equal_to: "total file size must be less than or equal to %{max} (current size is %{total_file_size})"
17+
total_file_size_not_greater_than: "total file size must be greater than %{min} (current size is %{total_file_size})"
18+
total_file_size_not_greater_than_or_equal_to: "total file size must be greater than or equal to %{min} (current size is %{total_file_size})"
19+
total_file_size_not_between: "total file size must be between %{min} and %{max} (current size is %{total_file_size})"
20+
duration_not_less_than: "duration must be less than %{max} (current duration is %{duration})"
21+
duration_not_less_than_or_equal_to: "duration must be less than or equal to %{max} (current duration is %{duration})"
22+
duration_not_greater_than: "duration must be greater than %{min} (current duration is %{duration})"
23+
duration_not_greater_than_or_equal_to: "duration must be greater than or equal to %{min} (current duration is %{duration})"
24+
duration_not_between: "duration must be between %{min} and %{max} (current duration is %{duration})"
25+
limit_out_of_range:
26+
zero: "no files attached (must have between %{min} and %{max} files)"
27+
one: "only 1 file attached (must have between %{min} and %{max} files)"
28+
other: "total number of files must be between %{min} and %{max} files (there are %{count} files attached)"
29+
limit_min_not_reached:
30+
zero: "no files attached (must have at least %{min} files)"
31+
one: "only 1 file attached (must have at least %{min} files)"
32+
other: "%{count} files attached (must have at least %{min} files)"
33+
limit_max_exceeded:
34+
zero: "no files attached (maximum is %{max} files)"
35+
one: "too many files attached (maximum is %{max} files, got %{count})"
36+
other: "too many files attached (maximum is %{max} files, got %{count})"
37+
attachment_missing: "is missing its attachment"
38+
media_metadata_missing: "is not a valid media file"
39+
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixel"
40+
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixel"
41+
dimension_width_not_included_in: "width is not included between %{min} and %{max} pixel"
42+
dimension_height_not_included_in: "height is not included between %{min} and %{max} pixel"
43+
dimension_width_not_greater_than_or_equal_to: "width must be greater than or equal to %{length} pixel"
44+
dimension_height_not_greater_than_or_equal_to: "height must be greater than or equal to %{length} pixel"
45+
dimension_width_not_less_than_or_equal_to: "width must be less than or equal to %{length} pixel"
46+
dimension_height_not_less_than_or_equal_to: "height must be less than or equal to %{length} pixel"
47+
dimension_width_not_equal_to: "width must be equal to %{length} pixel"
48+
dimension_height_not_equal_to: "height must be equal to %{length} pixel"
49+
aspect_ratio_not_square: "must be square (current file is %{width}x%{height}px)"
50+
aspect_ratio_not_portrait: "must be portrait (current file is %{width}x%{height}px)"
51+
aspect_ratio_not_landscape: "must be landscape (current file is %{width}x%{height}px)"
52+
aspect_ratio_not_x_y: "must be %{authorized_aspect_ratios} (current file is %{width}x%{height}px)"
53+
aspect_ratio_invalid: "has an invalid aspect ratio (valid aspect ratios are %{authorized_aspect_ratios})"
54+
file_not_processable: "is not identified as a valid media file"

config/locales/en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ en:
3434
zero: "no files attached (maximum is %{max} files)"
3535
one: "too many files attached (maximum is %{max} files, got %{count})"
3636
other: "too many files attached (maximum is %{max} files, got %{count})"
37+
attachment_missing: "is missing its attachment"
3738
media_metadata_missing: "is not a valid media file"
3839
dimension_min_not_included_in: "must be greater than or equal to %{width} x %{height} pixel"
3940
dimension_max_not_included_in: "must be less than or equal to %{width} x %{height} pixel"

config/locales/es.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ es:
3434
zero: "no hay archivos adjuntos (máximo es %{max} archivos)"
3535
one: "demasiados archivos adjuntos (máximo es %{max} archivos, got %{count})"
3636
other: "demasiados archivos adjuntos (máximo es %{max} archivos, got %{count})"
37+
attachment_missing: "no tiene archivo adjunto"
3738
media_metadata_missing: "no es un archivo multimedia válido"
3839
dimension_min_not_included_in: "debe ser mayor o igual a %{width} x %{height} pixel"
3940
dimension_max_not_included_in: "debe ser menor o igual a %{width} x %{height} pixel"

0 commit comments

Comments
 (0)