active_storage_validations 1.0.4 → 3.0.2

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +785 -245
  3. data/config/locales/da.yml +63 -0
  4. data/config/locales/de.yml +60 -19
  5. data/config/locales/en-GB.yml +63 -0
  6. data/config/locales/en.yml +60 -20
  7. data/config/locales/es.yml +60 -19
  8. data/config/locales/fr.yml +60 -19
  9. data/config/locales/it.yml +60 -19
  10. data/config/locales/ja.yml +60 -19
  11. data/config/locales/nl.yml +60 -19
  12. data/config/locales/pl.yml +60 -19
  13. data/config/locales/pt-BR.yml +60 -19
  14. data/config/locales/ru.yml +60 -19
  15. data/config/locales/sv.yml +63 -0
  16. data/config/locales/tr.yml +60 -19
  17. data/config/locales/uk.yml +60 -19
  18. data/config/locales/vi.yml +60 -19
  19. data/config/locales/zh-CN.yml +60 -19
  20. data/lib/active_storage_validations/analyzer/audio_analyzer.rb +58 -0
  21. data/lib/active_storage_validations/analyzer/content_type_analyzer.rb +60 -0
  22. data/lib/active_storage_validations/analyzer/image_analyzer/image_magick.rb +46 -0
  23. data/lib/active_storage_validations/analyzer/image_analyzer/vips.rb +56 -0
  24. data/lib/active_storage_validations/analyzer/image_analyzer.rb +49 -0
  25. data/lib/active_storage_validations/analyzer/null_analyzer.rb +18 -0
  26. data/lib/active_storage_validations/analyzer/pdf_analyzer.rb +89 -0
  27. data/lib/active_storage_validations/analyzer/shared/asv_ff_probable.rb +61 -0
  28. data/lib/active_storage_validations/analyzer/video_analyzer.rb +130 -0
  29. data/lib/active_storage_validations/analyzer.rb +88 -0
  30. data/lib/active_storage_validations/aspect_ratio_validator.rb +157 -97
  31. data/lib/active_storage_validations/attached_validator.rb +22 -5
  32. data/lib/active_storage_validations/base_comparison_validator.rb +83 -0
  33. data/lib/active_storage_validations/content_type_validator.rb +219 -31
  34. data/lib/active_storage_validations/dimension_validator.rb +187 -97
  35. data/lib/active_storage_validations/duration_validator.rb +70 -0
  36. data/lib/active_storage_validations/extensors/asv_blob_metadatable.rb +56 -0
  37. data/lib/active_storage_validations/extensors/asv_marcelable.rb +12 -0
  38. data/lib/active_storage_validations/limit_validator.rb +76 -9
  39. data/lib/active_storage_validations/matchers/aspect_ratio_validator_matcher.rb +119 -0
  40. data/lib/active_storage_validations/matchers/attached_validator_matcher.rb +48 -25
  41. data/lib/active_storage_validations/matchers/base_comparison_validator_matcher.rb +150 -0
  42. data/lib/active_storage_validations/matchers/content_type_validator_matcher.rb +98 -39
  43. data/lib/active_storage_validations/matchers/dimension_validator_matcher.rb +93 -55
  44. data/lib/active_storage_validations/matchers/duration_validator_matcher.rb +39 -0
  45. data/lib/active_storage_validations/matchers/limit_validator_matcher.rb +127 -0
  46. data/lib/active_storage_validations/matchers/pages_validator_matcher.rb +39 -0
  47. data/lib/active_storage_validations/matchers/processable_file_validator_matcher.rb +78 -0
  48. data/lib/active_storage_validations/matchers/shared/asv_active_storageable.rb +19 -0
  49. data/lib/active_storage_validations/matchers/shared/asv_allow_blankable.rb +28 -0
  50. data/lib/active_storage_validations/matchers/shared/asv_attachable.rb +72 -0
  51. data/lib/active_storage_validations/matchers/shared/asv_contextable.rb +57 -0
  52. data/lib/active_storage_validations/matchers/shared/asv_messageable.rb +28 -0
  53. data/lib/active_storage_validations/matchers/shared/asv_rspecable.rb +27 -0
  54. data/lib/active_storage_validations/matchers/shared/asv_validatable.rb +56 -0
  55. data/lib/active_storage_validations/matchers/size_validator_matcher.rb +17 -71
  56. data/lib/active_storage_validations/matchers/total_size_validator_matcher.rb +47 -0
  57. data/lib/active_storage_validations/matchers.rb +17 -21
  58. data/lib/active_storage_validations/pages_validator.rb +61 -0
  59. data/lib/active_storage_validations/processable_file_validator.rb +37 -0
  60. data/lib/active_storage_validations/railtie.rb +14 -0
  61. data/lib/active_storage_validations/shared/asv_active_storageable.rb +30 -0
  62. data/lib/active_storage_validations/shared/asv_analyzable.rb +89 -0
  63. data/lib/active_storage_validations/shared/asv_attachable.rb +236 -0
  64. data/lib/active_storage_validations/shared/asv_errorable.rb +64 -0
  65. data/lib/active_storage_validations/shared/asv_loggable.rb +11 -0
  66. data/lib/active_storage_validations/shared/asv_optionable.rb +29 -0
  67. data/lib/active_storage_validations/shared/asv_symbolizable.rb +14 -0
  68. data/lib/active_storage_validations/size_validator.rb +24 -41
  69. data/lib/active_storage_validations/total_size_validator.rb +52 -0
  70. data/lib/active_storage_validations/version.rb +1 -1
  71. data/lib/active_storage_validations.rb +27 -13
  72. metadata +113 -31
  73. data/lib/active_storage_validations/metadata.rb +0 -151
  74. data/lib/active_storage_validations/option_proc_unfolding.rb +0 -16
  75. data/lib/active_storage_validations/processable_image_validator.rb +0 -43
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveStorageValidations
6
+ module Matchers
7
+ module ASVMessageable
8
+ extend ActiveSupport::Concern
9
+
10
+ def initialize_messageable
11
+ @custom_message = nil
12
+ end
13
+
14
+ def with_message(custom_message)
15
+ @custom_message = custom_message
16
+ self
17
+ end
18
+
19
+ private
20
+
21
+ def has_an_error_message_which_is_custom_message?
22
+ validator_errors_for_attribute.one? do |error|
23
+ error[:custom_message] == @custom_message
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveStorageValidations
6
+ module Matchers
7
+ module ASVRspecable
8
+ extend ActiveSupport::Concern
9
+
10
+ def initialize_rspecable
11
+ @failure_message_artefacts = []
12
+ end
13
+
14
+ def description
15
+ raise NotImplementedError, "#{self.class} did not define #{__method__}"
16
+ end
17
+
18
+ def failure_message
19
+ raise NotImplementedError, "#{self.class} did not define #{__method__}"
20
+ end
21
+
22
+ def failure_message_when_negated
23
+ failure_message.sub(/is expected to validate/, "is expected not to validate")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveStorageValidations
6
+ module Matchers
7
+ module ASVValidatable
8
+ extend ActiveSupport::Concern
9
+
10
+ private
11
+
12
+ def validate
13
+ @subject.validate(@context)
14
+ end
15
+
16
+ def validator_errors_for_attribute
17
+ @subject.errors.details[@attribute_name].select do |error|
18
+ error[:validator_type] == validator_class.to_sym
19
+ end
20
+ end
21
+
22
+ def is_valid?
23
+ validator_errors_for_attribute.none? do |error|
24
+ error[:error].in?(available_errors)
25
+ end
26
+ end
27
+
28
+ def available_errors
29
+ [
30
+ *validator_class::ERROR_TYPES,
31
+ *errors_from_custom_messages
32
+ ].compact
33
+ end
34
+
35
+ def validator_class
36
+ self.class.name.gsub(/::Matchers|Matcher/, "").constantize
37
+ end
38
+
39
+ def attribute_validator
40
+ @subject.class.validators_on(@attribute_name).find do |validator|
41
+ validator.class == validator_class
42
+ end
43
+ end
44
+
45
+ def attribute_validators
46
+ @subject.class.validators_on(@attribute_name).select do |validator|
47
+ validator.class == validator_class
48
+ end
49
+ end
50
+
51
+ def errors_from_custom_messages
52
+ attribute_validators.map { |validator| validator.options[:message] }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,91 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Big thank you to the paperclip validation matchers:
4
- # https://github.com/thoughtbot/paperclip/blob/v6.1.0/lib/paperclip/matchers/validate_attachment_size_matcher.rb
3
+ require_relative "base_comparison_validator_matcher"
4
+
5
5
  module ActiveStorageValidations
6
6
  module Matchers
7
- def validate_size_of(name)
8
- SizeValidatorMatcher.new(name)
7
+ def validate_size_of(attribute_name)
8
+ SizeValidatorMatcher.new(attribute_name)
9
9
  end
10
10
 
11
- class SizeValidatorMatcher
12
- def initialize(attribute_name)
13
- @attribute_name = attribute_name
14
- @low = @high = nil
15
- end
16
-
11
+ class SizeValidatorMatcher < BaseComparisonValidatorMatcher
17
12
  def description
18
- "validate file size of #{@attribute_name}"
19
- end
20
-
21
- def less_than(size)
22
- @high = size - 1.byte
23
- self
24
- end
25
-
26
- def less_than_or_equal_to(size)
27
- @high = size
28
- self
29
- end
30
-
31
- def greater_than(size)
32
- @low = size + 1.byte
33
- self
34
- end
35
-
36
- def greater_than_or_equal_to(size)
37
- @low = size
38
- self
39
- end
40
-
41
- def between(range)
42
- @low, @high = range.first, range.last
43
- self
44
- end
45
-
46
- def matches?(subject)
47
- @subject = subject.is_a?(Class) ? subject.new : subject
48
- responds_to_methods && lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
13
+ "validate file size of :#{@attribute_name}"
49
14
  end
50
15
 
51
16
  def failure_message
52
- "is expected to validate file size of #{@attribute_name} to be between #{@low} and #{@high} bytes"
17
+ message = [ "is expected to validate file size of :#{@attribute_name}" ]
18
+ build_failure_message(message)
19
+ message.join("\n")
53
20
  end
54
21
 
55
- def failure_message_when_negated
56
- "is expected to not validate file size of #{@attribute_name} to be between #{@low} and #{@high} bytes"
57
- end
58
-
59
- protected
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
-
67
- def lower_than_low?
68
- @low.nil? || !passes_validation_with_size(@low - 1)
69
- end
70
-
71
- def higher_than_low?
72
- @low.nil? || passes_validation_with_size(@low + 1)
73
- end
22
+ private
74
23
 
75
- def lower_than_high?
76
- @high.nil? || @high == Float::INFINITY || passes_validation_with_size(@high - 1)
24
+ def failure_message_unit
25
+ "bytes"
77
26
  end
78
27
 
79
- def higher_than_high?
80
- @high.nil? || @high == Float::INFINITY || !passes_validation_with_size(@high + 1)
28
+ def smallest_measurement
29
+ 1.byte
81
30
  end
82
31
 
83
- def passes_validation_with_size(new_size)
84
- io = Tempfile.new('Hello world!')
85
- Matchers.stub_method(io, :size, new_size) do
86
- @subject.public_send(@attribute_name).attach(io: io, filename: 'test.png', content_type: 'image/pg')
87
- @subject.validate
88
- @subject.errors.details[@attribute_name].all? { |error| error[:error] != :file_size_out_of_range }
32
+ def mock_value_for(io, size)
33
+ Matchers.stub_method(io, :size, size) do
34
+ yield
89
35
  end
90
36
  end
91
37
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_comparison_validator_matcher"
4
+
5
+ module ActiveStorageValidations
6
+ module Matchers
7
+ def validate_total_size_of(attribute_name)
8
+ TotalSizeValidatorMatcher.new(attribute_name)
9
+ end
10
+
11
+ class TotalSizeValidatorMatcher < BaseComparisonValidatorMatcher
12
+ def description
13
+ "validate total file size of :#{@attribute_name}"
14
+ end
15
+
16
+ def failure_message
17
+ message = [ "is expected to validate total file size of :#{@attribute_name}" ]
18
+ build_failure_message(message)
19
+ message.join("\n")
20
+ end
21
+
22
+ protected
23
+
24
+ def attach_file
25
+ # has_many_attached relation
26
+ @subject.public_send(@attribute_name).attach([ dummy_blob ])
27
+ @subject.public_send(@attribute_name)
28
+ end
29
+
30
+ private
31
+
32
+ def failure_message_unit
33
+ "bytes"
34
+ end
35
+
36
+ def smallest_measurement
37
+ 1.byte
38
+ end
39
+
40
+ def mock_value_for(io, size)
41
+ Matchers.stub_method(io, :size, size) do
42
+ yield
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,9 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_storage_validations/matchers/attached_validator_matcher'
4
- require 'active_storage_validations/matchers/content_type_validator_matcher'
5
- require 'active_storage_validations/matchers/dimension_validator_matcher'
6
- require 'active_storage_validations/matchers/size_validator_matcher'
3
+ require "active_storage_validations/matchers/aspect_ratio_validator_matcher"
4
+ require "active_storage_validations/matchers/attached_validator_matcher"
5
+ require "active_storage_validations/matchers/processable_file_validator_matcher"
6
+ require "active_storage_validations/matchers/limit_validator_matcher"
7
+ require "active_storage_validations/matchers/content_type_validator_matcher"
8
+ require "active_storage_validations/matchers/dimension_validator_matcher"
9
+ require "active_storage_validations/matchers/duration_validator_matcher"
10
+ require "active_storage_validations/matchers/size_validator_matcher"
11
+ require "active_storage_validations/matchers/total_size_validator_matcher"
12
+ require "active_storage_validations/matchers/pages_validator_matcher"
7
13
 
8
14
  module ActiveStorageValidations
9
15
  module Matchers
@@ -17,26 +23,16 @@ module ActiveStorageValidations
17
23
  RSpec::Mocks.allow_message(object, method) { result }
18
24
  yield
19
25
  else
20
- raise 'Need either Minitest::Mock or RSpec::Mocks to run this validator matcher'
26
+ raise "Need either Minitest::Mock or RSpec::Mocks to run this validator matcher"
21
27
  end
22
28
  end
23
29
 
24
- def self.mock_metadata(attachment, width, height)
25
- if Rails.gem_version >= Gem::Version.new('6.0.0')
26
- # Mock the Metadata class for rails 6
27
- mock = OpenStruct.new(metadata: { width: width, height: height })
28
- stub_method(ActiveStorageValidations::Metadata, :new, mock) do
29
- yield
30
- end
31
- else
32
- # Stub the metadata analysis for rails 5
33
- stub_method(attachment, :analyze, true) do
34
- stub_method(attachment, :analyzed?, true) do
35
- stub_method(attachment, :metadata, { width: width, height: height }) do
36
- yield
37
- end
38
- end
39
- end
30
+ def self.mock_metadata(attachment, metadata = {})
31
+ asv_metadata_available_keys = { width: nil, height: nil, duration: nil, content_type: nil }
32
+ mock = Struct.new(:metadata).new(asv_metadata_available_keys.merge(metadata)) # ensure all keys are present, and it does not raise while trying to access them
33
+
34
+ stub_method(ActiveStorageValidations::Analyzer, :new, mock) do
35
+ yield
40
36
  end
41
37
  end
42
38
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_comparison_validator"
4
+ require_relative "shared/asv_analyzable"
5
+ require_relative "shared/asv_attachable"
6
+
7
+ module ActiveStorageValidations
8
+ class PagesValidator < BaseComparisonValidator
9
+ include ASVAnalyzable
10
+ include ASVAttachable
11
+
12
+ ERROR_TYPES = %i[
13
+ pages_not_less_than
14
+ pages_not_less_than_or_equal_to
15
+ pages_not_greater_than
16
+ pages_not_greater_than_or_equal_to
17
+ pages_not_between
18
+ pages_not_equal_to
19
+ ].freeze
20
+ METADATA_KEYS = %i[pages].freeze
21
+
22
+ delegate :number_to_delimited, to: ActiveSupport::NumberHelper
23
+
24
+ def validate_each(record, attribute, _value)
25
+ return if no_attachments?(record, attribute)
26
+
27
+ validate_changed_files_from_metadata(record, attribute, METADATA_KEYS)
28
+ end
29
+
30
+ private
31
+
32
+ def is_valid?(record, attribute, file, metadata)
33
+ flat_options = set_flat_options(record)
34
+ errors_options = initialize_error_options(options, file)
35
+
36
+ unless valid_metadata?(metadata)
37
+ add_media_metadata_missing_error(record, attribute, file, errors_options)
38
+ return false
39
+ end
40
+
41
+ return true if super(metadata[:pages], flat_options)
42
+
43
+ populate_error_options(errors_options, flat_options)
44
+ errors_options[:pages] = format_bound_value(metadata[:pages])
45
+
46
+ keys = AVAILABLE_CHECKS & flat_options.keys
47
+ error_type = "pages_not_#{keys.first}".to_sym
48
+
49
+ add_error(record, attribute, error_type, **errors_options)
50
+ false
51
+ end
52
+
53
+ def valid_metadata?(metadata)
54
+ metadata[:pages].to_i > 0
55
+ end
56
+
57
+ def format_bound_value(value)
58
+ number_to_delimited(value)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "shared/asv_active_storageable"
4
+ require_relative "shared/asv_analyzable"
5
+ require_relative "shared/asv_attachable"
6
+ require_relative "shared/asv_errorable"
7
+ require_relative "shared/asv_symbolizable"
8
+
9
+ module ActiveStorageValidations
10
+ class ProcessableFileValidator < ActiveModel::EachValidator # :nodoc
11
+ include ASVActiveStorageable
12
+ include ASVAnalyzable
13
+ include ASVAttachable
14
+ include ASVErrorable
15
+ include ASVSymbolizable
16
+
17
+ ERROR_TYPES = %i[
18
+ file_not_processable
19
+ ].freeze
20
+ METADATA_KEYS = %i[].freeze
21
+
22
+ def validate_each(record, attribute, _value)
23
+ return if no_attachments?(record, attribute)
24
+
25
+ validate_changed_files_from_metadata(record, attribute, METADATA_KEYS)
26
+ end
27
+
28
+ private
29
+
30
+ def is_valid?(record, attribute, attachable, metadata)
31
+ return if !metadata.empty?
32
+
33
+ errors_options = initialize_error_options(options, attachable)
34
+ add_error(record, attribute, ERROR_TYPES.first, **errors_options)
35
+ end
36
+ end
37
+ end
@@ -2,5 +2,19 @@
2
2
 
3
3
  module ActiveStorageValidations
4
4
  class Railtie < ::Rails::Railtie
5
+ # Using after: :load_config_initializers would cause a stack level too deep error
6
+ # See: https://github.com/igorkasyanchuk/active_storage_validations/issues/364
7
+
8
+ initializer "active_storage_validations.configure" do
9
+ ActiveSupport.on_load(:active_record) do
10
+ include ActiveStorageValidations
11
+ end
12
+ end
13
+
14
+ initializer "active_storage_validations.extend_active_storage_blob" do
15
+ ActiveSupport.on_load(:active_storage_blob) do
16
+ include ActiveStorageValidations::ASVBlobMetadatable
17
+ end
18
+ end
5
19
  end
6
20
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveStorageValidations
4
+ # ActiveStorageValidations::ASVActiveStorageable
5
+ #
6
+ # Validator helper methods to make our code more explicit.
7
+ module ASVActiveStorageable
8
+ extend ActiveSupport::Concern
9
+
10
+ private
11
+
12
+ # Retrieve either an `ActiveStorage::Attached::One` or an
13
+ # `ActiveStorage::Attached::Many` instance depending on attribute definition
14
+ def attached_files(record, attribute)
15
+ Array.wrap(record.send(attribute))
16
+ end
17
+
18
+ def attachments_present?(record, attribute)
19
+ record.send(attribute).attached?
20
+ end
21
+
22
+ def no_attachments?(record, attribute)
23
+ !attachments_present?(record, attribute)
24
+ end
25
+
26
+ def will_have_attachments_after_save?(record, attribute)
27
+ !Array.wrap(record.send(attribute)).all?(&:marked_for_destruction?)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveStorageValidations
4
+ # ActiveStorageValidations::ASVAnalyzable
5
+ #
6
+ # Validator methods for choosing the right analyzer depending on the file
7
+ # media type and available third-party analyzers.
8
+ module ASVAnalyzable
9
+ extend ActiveSupport::Concern
10
+
11
+ DEFAULT_IMAGE_PROCESSOR = :mini_magick.freeze
12
+
13
+ private
14
+
15
+ # Retrieve the ASV metadata from the blob.
16
+ # If the blob has not been analyzed by our gem yet, the gem will analyze the
17
+ # attachable with the corresponding analyzer and set the metadata in the
18
+ # blob.
19
+ def metadata_for(blob, attachable, metadata_keys)
20
+ return blob.active_storage_validations_metadata if blob_has_asv_metadata?(blob, metadata_keys)
21
+
22
+ new_metadata = generate_metadata_for(attachable, metadata_keys)
23
+ blob.merge_into_active_storage_validations_metadata(new_metadata)
24
+ blob.save!
25
+
26
+ blob.active_storage_validations_metadata
27
+ end
28
+
29
+ def blob_has_asv_metadata?(blob, metadata_keys)
30
+ return false unless blob.active_storage_validations_metadata.present?
31
+
32
+ metadata_keys.all? { |key| blob.active_storage_validations_metadata.key?(key) }
33
+ end
34
+
35
+ def generate_metadata_for(attachable, metadata_keys)
36
+ if metadata_keys == ActiveStorageValidations::ContentTypeValidator::METADATA_KEYS
37
+ content_type_analyzer_for(attachable).content_type
38
+ else
39
+ metadata_analyzer_for(attachable).metadata
40
+ end
41
+ end
42
+
43
+ def metadata_analyzer_for(attachable)
44
+ return pdf_analyzer_for(attachable) if attachable_content_type(attachable) == "application/pdf"
45
+
46
+ case attachable_media_type(attachable)
47
+ when "image" then image_analyzer_for(attachable)
48
+ when "video" then video_analyzer_for(attachable)
49
+ when "audio" then audio_analyzer_for(attachable)
50
+ else fallback_analyzer_for(attachable)
51
+ end
52
+ end
53
+
54
+ def pdf_analyzer_for(attachable)
55
+ ActiveStorageValidations::Analyzer::PdfAnalyzer.new(attachable)
56
+ end
57
+
58
+ def image_analyzer_for(attachable)
59
+ case image_processor
60
+ when :mini_magick
61
+ ActiveStorageValidations::Analyzer::ImageAnalyzer::ImageMagick.new(attachable)
62
+ when :vips
63
+ ActiveStorageValidations::Analyzer::ImageAnalyzer::Vips.new(attachable)
64
+ end
65
+ end
66
+
67
+ def image_processor
68
+ # Rails returns nil for default image processor, because it is set in an after initialize callback
69
+ # https://github.com/rails/rails/blob/main/activestorage/lib/active_storage/engine.rb
70
+ ActiveStorage.variant_processor || DEFAULT_IMAGE_PROCESSOR
71
+ end
72
+
73
+ def video_analyzer_for(attachable)
74
+ ActiveStorageValidations::Analyzer::VideoAnalyzer.new(attachable)
75
+ end
76
+
77
+ def audio_analyzer_for(attachable)
78
+ ActiveStorageValidations::Analyzer::AudioAnalyzer.new(attachable)
79
+ end
80
+
81
+ def fallback_analyzer_for(attachable)
82
+ ActiveStorageValidations::Analyzer::NullAnalyzer.new(attachable)
83
+ end
84
+
85
+ def content_type_analyzer_for(attachable)
86
+ ActiveStorageValidations::Analyzer::ContentTypeAnalyzer.new(attachable)
87
+ end
88
+ end
89
+ end