class Decidim::FileValidatorHumanizer

This class fetches the file validation conditions from the active record model objects which have specific validators and uploaders attached to them. This class is used to convert these validation conditions to a human readable format in the front-end and to simplify the code where these are needed from.

This considers if the validation conditions and the uploader have been set directly to the record being validated or if they should be read from another object in case the PassthruValidator is in charge of the validations.

Attributes

attribute[R]
passthru_validator[R]
record[R]

Public Class Methods

new(record, attribute) click to toggle source
# File lib/decidim/file_validator_humanizer.rb, line 15
def initialize(record, attribute)
  @record = record
  @attribute = attribute
  @passthru_validator ||= record.singleton_class.validators_on(
    attribute
  ).find { |validator| validator.is_a?(PassthruValidator) }
end

Public Instance Methods

extension_allowlist() click to toggle source

rubocop: enable Metrics/CyclomaticComplexity

# File lib/decidim/file_validator_humanizer.rb, line 76
def extension_allowlist
  return unless uploader.respond_to?(:extension_allowlist, true)

  # It may be a private method in some uploaders which is why we need to use
  # `#send`.
  uploader.send(:extension_allowlist)
end
max_file_size() click to toggle source

rubocop: disable Metrics/CyclomaticComplexity

# File lib/decidim/file_validator_humanizer.rb, line 51
def max_file_size
  # First try if the record itself has a file size validator defined.
  validator = record.singleton_class.validators_on(attribute).find do |v|
    v.is_a?(::ActiveModel::Validations::FileSizeValidator)
  end
  if validator
    lte = validator.options[:less_than_or_equal_to]
    return lte if lte.is_a?(Numeric)
    return lte.call(record) if lte.respond_to?(:call)
  end
  return unless passthru_validator

  # If not, check for the same validator from the pass through record.
  validator = passthru_validator.target_validators(attribute).find do |v|
    v.is_a?(::ActiveModel::Validations::FileSizeValidator)
  end
  return unless validator

  lte = validator.options[:less_than_or_equal_to]
  return lte if lte.is_a?(Numeric)

  lte.call(passthru_record) if lte.respond_to?(:call)
end
messages() click to toggle source
# File lib/decidim/file_validator_humanizer.rb, line 27
def messages
  messages = []

  if (file_size = max_file_size)
    file_size_mb = (((file_size / 1024 / 1024) * 100) / 100).round
    messages << I18n.t(
      "max_file_size",
      megabytes: file_size_mb,
      scope: "decidim.forms.file_validation"
    )
  end

  if (extensions = extension_allowlist)
    messages << I18n.t(
      "allowed_file_extensions",
      extensions: extensions.join(" "),
      scope: "decidim.forms.file_validation"
    )
  end

  messages
end
uploader() click to toggle source
# File lib/decidim/file_validator_humanizer.rb, line 23
def uploader
  @uploader ||= passthru_uploader || record.send(attribute)
end

Private Instance Methods

passthru_record() click to toggle source
# File lib/decidim/file_validator_humanizer.rb, line 88
def passthru_record
  return unless passthru_validator

  @passthru_record ||= passthru_validator.validation_record(record)
end
passthru_uploader() click to toggle source
# File lib/decidim/file_validator_humanizer.rb, line 94
def passthru_uploader
  return unless passthru_record

  passthru_record.send(passthru_validator.target_attribute(attribute))
end