Class: ActiveStorageValidations::DimensionValidator

Inherits:
ActiveModel::EachValidator
  • Object
show all
Defined in:
lib/active_storage_validations/dimension_validator.rb

Overview

:nodoc

Constant Summary collapse

AVAILABLE_CHECKS =
%i[width height min max].freeze

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ DimensionValidator

Returns a new instance of DimensionValidator.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/active_storage_validations/dimension_validator.rb', line 9

def initialize(options)
  [:width, :height].each do |length|
    if options[length] and options[length].is_a?(Hash)
      if range = options[length][:in]
        raise ArgumentError, ":in must be a Range" unless range.is_a?(Range)
        options[length][:min], options[length][:max] = range.min, range.max
      end
    end
  end
  [:min, :max].each do |dim|
    if range = options[dim]
      raise ArgumentError, ":#{dim} must be a Range (width..height)" unless range.is_a?(Range)
      options[:width] = { dim => range.first }
      options[:height] = { dim => range.last }
    end
  end
  super
end

Instance Method Details

#add_error(record, attribute, type, **attrs) ⇒ Object



120
121
122
123
124
# File 'lib/active_storage_validations/dimension_validator.rb', line 120

def add_error(record, attribute, type, **attrs)
  key = options[:message].presence || type
  return if record.errors.added?(attribute, key)
  record.errors.add(attribute, key, **attrs)
end

#check_validity!Object

Raises:

  • (ArgumentError)


29
30
31
32
# File 'lib/active_storage_validations/dimension_validator.rb', line 29

def check_validity!
  return true if AVAILABLE_CHECKS.any? { |argument| options.key?(argument) }
  raise ArgumentError, 'You must pass either :width, :height, :min or :max to the validator'
end

#is_valid?(record, attribute, file_metadata) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/active_storage_validations/dimension_validator.rb', line 66

def is_valid?(record, attribute, )
  # Validation fails unless file metadata contains valid width and height.
  if [:width].to_i <= 0 || [:height].to_i <= 0
    add_error(record, attribute, options[:message].presence || :image_metadata_missing)
    return false
  end

  # Validation based on checks :min and :max (:min, :max has higher priority to :width, :height).
  if options[:min] || options[:max]
    if options[:min] && (
      (options[:width][:min] && [:width] < options[:width][:min]) ||
      (options[:height][:min] && [:height] < options[:height][:min])
      )
      add_error(record, attribute, options[:message].presence || :"dimension_min_inclusion", width: options[:width][:min], height: options[:height][:min])
      return false
    end
    if options[:max] && (
      (options[:width][:max] && [:width] > options[:width][:max]) ||
      (options[:height][:max] && [:height] > options[:height][:max])
      )
      add_error(record, attribute, options[:message].presence || :"dimension_max_inclusion", width: options[:width][:max], height: options[:height][:max])
      return false
    end

  # Validation based on checks :width and :height.
  else
    [:width, :height].each do |length|
      next unless options[length]
      if options[length].is_a?(Hash)
        if options[length][:in] && ([length] < options[length][:min] || [length] > options[length][:max])
          add_error(record, attribute, options[:message].presence || :"dimension_#{length}_inclusion", min: options[length][:min], max: options[length][:max])
          return false
        else
          if options[length][:min] && [length] < options[length][:min]
            add_error(record, attribute, options[:message].presence || :"dimension_#{length}_greater_than_or_equal_to", length: options[length][:min])
            return false
          end
          if options[length][:max] && [length] > options[length][:max]
            add_error(record, attribute, options[:message].presence || :"dimension_#{length}_less_than_or_equal_to", length: options[length][:max])
            return false
          end
        end
      else
        if [length] != options[length]
          add_error(record, attribute, options[:message].presence || :"dimension_#{length}_equal_to", length: options[length])
          return false
        end
      end
    end
  end

  true # valid file
end

#validate_each(record, attribute, _value) ⇒ Object

Rails 5



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/active_storage_validations/dimension_validator.rb', line 51

def validate_each(record, attribute, _value)
  return true unless record.send(attribute).attached?

  changes = record.attachment_changes[attribute.to_s]
  return true if changes.blank?

  files = Array.wrap(changes.is_a?(ActiveStorage::Attached::Changes::CreateMany) ? changes.attachables : changes.attachable)
  files.each do |file|
     = Metadata.new(file).
    next if is_valid?(record, attribute, )
    break
  end
end