active_storage_validations 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3fa76d4dc0cf3d5bffc62dcc604d6f38edf165931c94d9314288606b6205a56
4
- data.tar.gz: 9adb8defb7d44c65a4ea67cf632087d423a1c2c44b918822653638132f8beef4
3
+ metadata.gz: a7b0998dd3938eee42be49dc3d831eaea8482001a0e03227f61cc0330050a3a1
4
+ data.tar.gz: 72a82d3965c026f118bd1d4bc7e0338a2313c43394f780577cbbe944356caf39
5
5
  SHA512:
6
- metadata.gz: 9a2d4ce5113ed8a018d71b4d40b01c11946892eea438d2b7481b7007511022695998271d06215e6ddf07929d4e057fc8411a2b0babcb508f70af6140fb4d65c8
7
- data.tar.gz: 3d31b7848f3174a8df330e5410b5c1aec018a243bfdefa2abdfc8eee9d9f652e34645853da38dee2b1627ef42efa679fabdac11e896a6a37ce9cd0ed1c5569f7
6
+ metadata.gz: a0117ebfeed615802b45e4f341eea6e5676d8189e4a4bf81faa565e8e49f418142a7aa3466a6cd3f92761e029ff54f58298259ae390682649d5ad5950e52d787
7
+ data.tar.gz: e6ab73fe085110abe6b346e3eb837a59ca81b499707cdbf8df9773647feefd7b11ca4e5be03329226954a43756a5ceda9550169ff5402a6f275cfc7b4865f6b9
data/README.md CHANGED
@@ -19,6 +19,7 @@ This gems doing it for you. Just use `attached: true` or `content_type: 'image/p
19
19
  * validates dimension of images/videos
20
20
  * validates number of uploaded files (min/max required)
21
21
  * validates aspect ratio (if square, portrait, landscape, is_16_9, ...)
22
+ * validates if file can be processed by MiniMagick or Vips
22
23
  * custom error messages
23
24
  * allow procs for dynamic determination of values
24
25
 
@@ -40,6 +41,7 @@ class User < ApplicationRecord
40
41
  dimension: { width: { min: 800, max: 2400 },
41
42
  height: { min: 600, max: 1800 }, message: 'is not given between dimension' }
42
43
  validates :image, attached: true,
44
+ processable_image: true,
43
45
  content_type: ['image/png', 'image/jpeg'],
44
46
  aspect_ratio: :landscape
45
47
  end
@@ -164,6 +166,7 @@ en:
164
166
  aspect_ratio_not_landscape: "must be a landscape image"
165
167
  aspect_ratio_is_not: "must have an aspect ratio of %{aspect_ratio}"
166
168
  aspect_ratio_unknown: "has an unknown aspect ratio"
169
+ image_not_processable: "is not a valid image"
167
170
  ```
168
171
 
169
172
  In some cases, Active Storage Validations provides variables to help you customize messages:
@@ -311,9 +314,9 @@ end
311
314
 
312
315
  To run tests in root folder of gem:
313
316
 
314
- * `BUNDLE_GEMFILE=gemfiles/rails_5_2.gemfile bundle exec rake test` to run for Rails 5.2
315
317
  * `BUNDLE_GEMFILE=gemfiles/rails_6_0.gemfile bundle exec rake test` to run for Rails 6.0
316
318
  * `BUNDLE_GEMFILE=gemfiles/rails_6_1.gemfile bundle exec rake test` to run for Rails 6.1
319
+ * `BUNDLE_GEMFILE=gemfiles/rails_7_0.gemfile bundle exec rake test` to run for Rails 7.0
317
320
  * `BUNDLE_GEMFILE=gemfiles/rails_next.gemfile bundle exec rake test` to run for Rails main branch
318
321
 
319
322
  Snippet to run in console:
@@ -395,6 +398,8 @@ You are welcome to contribute.
395
398
  = https://github.com/gr8bit
396
399
  = https://github.com/codegeek319
397
400
  = https://github.com/clwy-cn
401
+ = https://github.com/kukicola
402
+ = https://github.com/sobrinho
398
403
 
399
404
  ## License
400
405
 
@@ -20,3 +20,4 @@ en:
20
20
  aspect_ratio_not_landscape: "must be a landscape image"
21
21
  aspect_ratio_is_not: "must have an aspect ratio of %{aspect_ratio}"
22
22
  aspect_ratio_unknown: "has an unknown aspect ratio"
23
+ image_not_processable: "is not a valid image"
@@ -33,15 +33,19 @@ module ActiveStorageValidations
33
33
  end
34
34
 
35
35
  def failure_message
36
- <<~MESSAGE
37
- Expected #{@attribute_name}
36
+ message = ["Expected #{@attribute_name}"]
38
37
 
39
- Accept content types: #{allowed_types.join(", ")}
40
- #{accepted_types_and_failures}
38
+ if @allowed_types
39
+ message << "Accept content types: #{allowed_types.join(", ")}"
40
+ message << "#{@missing_allowed_types.join(", ")} were rejected"
41
+ end
42
+
43
+ if @rejected_types
44
+ message << "Reject content types: #{rejected_types.join(", ")}"
45
+ message << "#{@missing_rejected_types.join(", ")} were accepted"
46
+ end
41
47
 
42
- Reject content types: #{rejected_types.join(", ")}
43
- #{rejected_types_and_failures}
44
- MESSAGE
48
+ message.join("\n")
45
49
  end
46
50
 
47
51
  protected
@@ -57,7 +61,7 @@ module ActiveStorageValidations
57
61
  end
58
62
 
59
63
  def rejected_types
60
- @rejected_types || (content_type_keys - allowed_types)
64
+ @rejected_types || []
61
65
  end
62
66
 
63
67
  def allowed_types_allowed?
@@ -70,22 +74,6 @@ module ActiveStorageValidations
70
74
  @missing_rejected_types.none?
71
75
  end
72
76
 
73
- def accepted_types_and_failures
74
- if @missing_allowed_types.present?
75
- "#{@missing_allowed_types.join(", ")} were rejected."
76
- else
77
- "All were accepted successfully."
78
- end
79
- end
80
-
81
- def rejected_types_and_failures
82
- if @missing_rejected_types.present?
83
- "#{@missing_rejected_types.join(", ")} were accepted."
84
- else
85
- "All were rejected successfully."
86
- end
87
- end
88
-
89
77
  def type_allowed?(type)
90
78
  @subject.public_send(@attribute_name).attach(attachment_for(type))
91
79
  @subject.validate
@@ -96,16 +84,6 @@ module ActiveStorageValidations
96
84
  suffix = type.to_s.split('/').last
97
85
  { io: Tempfile.new('.'), filename: "test.#{suffix}", content_type: type }
98
86
  end
99
-
100
- private
101
-
102
- def content_type_keys
103
- if Rails.gem_version < Gem::Version.new('6.1.0')
104
- Mime::LOOKUP.keys
105
- else
106
- Marcel::TYPES.keys
107
- end
108
- end
109
87
  end
110
88
  end
111
89
  end
@@ -1,5 +1,7 @@
1
1
  module ActiveStorageValidations
2
2
  class Metadata
3
+ class InvalidImageError < StandardError; end
4
+
3
5
  attr_reader :file
4
6
 
5
7
  def initialize(file)
@@ -10,7 +12,7 @@ module ActiveStorageValidations
10
12
  def image_processor
11
13
  Rails.application.config.active_storage.variant_processor
12
14
  end
13
-
15
+
14
16
  def exception_class
15
17
  if image_processor == :vips && defined?(Vips)
16
18
  Vips::Error
@@ -35,6 +37,16 @@ module ActiveStorageValidations
35
37
  { width: image.width, height: image.height }
36
38
  end
37
39
  end
40
+ rescue InvalidImageError
41
+ logger.info "Skipping image analysis because ImageMagick or Vips doesn't support the file"
42
+ {}
43
+ end
44
+
45
+ def valid?
46
+ read_image
47
+ true
48
+ rescue InvalidImageError
49
+ false
38
50
  end
39
51
 
40
52
  private
@@ -76,12 +88,9 @@ module ActiveStorageValidations
76
88
  end
77
89
  end
78
90
 
79
- if image && valid_image?(image)
80
- yield image
81
- else
82
- logger.info "Skipping image analysis because ImageMagick or Vips doesn't support the file"
83
- {}
84
- end
91
+
92
+ raise InvalidImageError unless valid_image?(image)
93
+ yield image
85
94
  rescue LoadError, NameError
86
95
  logger.info "Skipping image analysis because the mini_magick or ruby-vips gem isn't installed"
87
96
  {}
@@ -93,6 +102,8 @@ module ActiveStorageValidations
93
102
  end
94
103
 
95
104
  def valid_image?(image)
105
+ return false unless image
106
+
96
107
  image_processor == :vips && image.is_a?(Vips::Image) ? image.avg : image.valid?
97
108
  rescue exception_class
98
109
  false
@@ -1,10 +1,10 @@
1
1
  module ActiveStorageValidations
2
2
  module OptionProcUnfolding
3
3
 
4
- def unfold_procs(record, object, only_keys = nil)
4
+ def unfold_procs(record, object, only_keys)
5
5
  case object
6
6
  when Hash
7
- object.merge(object) { |key, value| only_keys&.exclude?(key) ? unfold_procs(record, value, []) : unfold_procs(record, value) }
7
+ object.merge(object) { |key, value| only_keys&.exclude?(key) ? {} : unfold_procs(record, value, nil) }
8
8
  when Array
9
9
  object.map { |o| unfold_procs(record, o, only_keys) }
10
10
  else
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'metadata.rb'
4
+
5
+ module ActiveStorageValidations
6
+ class ProcessableImageValidator < ActiveModel::EachValidator # :nodoc
7
+ include OptionProcUnfolding
8
+
9
+ if Rails.gem_version >= Gem::Version.new('6.0.0')
10
+ def validate_each(record, attribute, _value)
11
+ return true unless record.send(attribute).attached?
12
+
13
+ changes = record.attachment_changes[attribute.to_s]
14
+ return true if changes.blank?
15
+
16
+ files = Array.wrap(changes.is_a?(ActiveStorage::Attached::Changes::CreateMany) ? changes.attachables : changes.attachable)
17
+
18
+ files.each do |file|
19
+ add_error(record, attribute, :image_not_processable) unless Metadata.new(file).valid?
20
+ end
21
+ end
22
+ else
23
+ # Rails 5
24
+ def validate_each(record, attribute, _value)
25
+ return true unless record.send(attribute).attached?
26
+
27
+ files = Array.wrap(record.send(attribute))
28
+
29
+ files.each do |file|
30
+ add_error(record, attribute, :image_not_processable) unless Metadata.new(file).valid?
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def add_error(record, attribute, default_message)
38
+ message = options[:message].presence || default_message
39
+ return if record.errors.added?(attribute, message)
40
+ record.errors.add(attribute, message)
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorageValidations
4
- VERSION = '1.0.0'
4
+ VERSION = '1.0.2'
5
5
  end
@@ -9,6 +9,7 @@ require 'active_storage_validations/size_validator'
9
9
  require 'active_storage_validations/limit_validator'
10
10
  require 'active_storage_validations/dimension_validator'
11
11
  require 'active_storage_validations/aspect_ratio_validator'
12
+ require 'active_storage_validations/processable_image_validator'
12
13
 
13
14
  ActiveSupport.on_load(:active_record) do
14
15
  send :include, ActiveStorageValidations
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_storage_validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-05 00:00:00.000000000 Z
11
+ date: 2022-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -216,6 +216,7 @@ files:
216
216
  - lib/active_storage_validations/matchers/size_validator_matcher.rb
217
217
  - lib/active_storage_validations/metadata.rb
218
218
  - lib/active_storage_validations/option_proc_unfolding.rb
219
+ - lib/active_storage_validations/processable_image_validator.rb
219
220
  - lib/active_storage_validations/railtie.rb
220
221
  - lib/active_storage_validations/size_validator.rb
221
222
  - lib/active_storage_validations/version.rb