Sha256: 071ab27cec2d79cd017e9ecc5e77b5e0e521425ad2845084e43d7c8aa6185620

Contents?: true

Size: 1.95 KB

Versions: 1

Compression:

Stored size: 1.95 KB

Contents

class MeasuredValidator < ActiveModel::EachValidator
  CHECKS = {
    greater_than: :>,
    greater_than_or_equal_to: :>=,
    equal_to: :==,
    less_than: :<,
    less_than_or_equal_to: :<=,
  }.freeze

  def validate_each(record, attribute, measurable)
    measured_config = record.class.measured_fields[attribute]

    measured_class = measured_config[:class]
    measurable_unit = record.public_send("#{ attribute }_unit")
    measurable_value = record.public_send("#{ attribute }_value")

    return unless measurable_unit.present? || measurable_value.present?

    record.errors.add(attribute, message("cannot be blank")) if [measurable_unit.blank?, measurable_value.blank?].any?

    record.errors.add(attribute, message("is not a valid unit")) unless measured_class.valid_unit?(measurable_unit)

    if options[:units]
      valid_units = [options[:units]].flatten.map{|u| measured_class.conversion.to_unit_name(u) }
      record.errors.add(attribute, message("is not a valid unit")) unless valid_units.include?(measured_class.conversion.to_unit_name(measurable_unit))
    end

    if measured_class.valid_unit?(measurable_unit)
      options.slice(*CHECKS.keys).each do |option, value|
        comparable_value = value_for(value, record)
        comparable_value = measured_class.new(comparable_value, measurable_unit) if comparable_value.is_a?(Numeric)
        unless measurable.public_send(CHECKS[option], comparable_value)
          record.errors.add(attribute, message("#{measurable.to_s} must be #{CHECKS[option]} #{comparable_value}"))
        end
      end
    end
  end

  private

  def message(default_message)
    options[:message] || default_message
  end

  def value_for(key, record)
    value = case key
    when Proc
      key.call(record)
    when Symbol
      record.send(key)
    else
      key
    end

    raise ArgumentError, ":#{ value } must be a number or a Measurable object" unless (value.is_a?(Numeric) || value.is_a?(Measured::Measurable))
    value
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
measured-rails-1.3.1 lib/measured/rails/validations.rb