dobtco/procure-io

View on GitHub
lib/responsable_validator.rb

Summary

Maintainability
C
1 day
Test Coverage
# @todo cleanup and test
class ResponsableValidator
  attr_accessor :errors

  def initialize(response_fields, responses)
    @errors = []

    response_fields.each do |response_field|
      response = responses.select { |response| response.response_field_id == response_field.id}.first
      value = response ? response.value : nil

      next if required_field(response_field, response, value)

      [:min_max_length, :min_max, :integer_only,
       :valid_website, :valid_date, :valid_time].each { |x| send x, response_field, response, value }
    end
  end

  private
  def required_field(response_field, response, value)
    return false if !response_field.field_options["required"] || # field is not required
                    (response && response.upload?) || # file has been uploaded
                    (value && !value.blank? && !value.is_a?(Hash)) || # value isn't blank (ignore hashes)
                    (response_field.field_type.in?(ResponseField::OPTIONS_FIELDS) && (response_field.field_options["options"] || []).empty?) ||
                    response_field.field_type == "checkboxes" && value && value.reject{|k, v| !v}.length > 0 || # required checkboxes have at least one checkbox checked
                    response_field.field_type == "time" && value && (!value['hours'].blank? || !value['minutes'].blank? || !value['seconds'].blank?) || # there is input in the time field
                    response_field.field_type == "date" && value && (!value['year'].blank? || !value['month'].blank? || !value['day'].blank?) # there is input in the time field

    @errors << "#{response_field.label} is a required field."
  end

  def min_max_length(response_field, response, value)
    if response_field.field_options["minlength"] && (!value || value.length < response_field.field_options["minlength"].to_i)
      @errors << "#{response_field.label} is too short. It should be #{response_field.field_options["minlength"]} characters or more."
    end

    if response_field.field_options["maxlength"] && (!value || value.length > response_field.field_options["maxlength"].to_i)
      @errors << "#{response_field.label} is too long. It should be #{response_field.field_options["maxlength"]} characters or less."
    end
  end

  def min_max(response_field, response, value)
    if response_field.field_options["min"] && (value.to_f < response_field.field_options["min"].to_f)
      @errors << "#{response_field.label} is too small. It should be #{response_field.field_options["min"]} or more."
    end

    if response_field.field_options["max"] && (value.to_f > response_field.field_options["max"].to_f)
      @errors << "#{response_field.label} is too large. It should be #{response_field.field_options["max"]} or less."
    end
  end

  def integer_only(response_field, response, value)
    if response_field.field_options["integer_only"] && !(Integer(value) rescue false)
      @errors << "#{response_field.label} needs to be an integer."
    end
  end

  def valid_website(response_field, response, value)
    return if response_field.field_type != "website"
    require 'uri'
    if !(value =~ URI::regexp)
      @errors << "#{response_field.label} isn't a valid URL."
    end
  end

  def valid_date(response_field, response, value)
    return if response_field.field_type != "date"
    if !(DateTime.new(value['year'].to_i, value['month'].to_i, value['day'].to_i) rescue false)
      @errors << "#{response_field.label} isn't a valid date."
    end
  end

  def valid_time(response_field, response, value)
    return if response_field.field_type != "time"
    if !value['hours'].to_i.between?(1, 12) || !value['minutes'].to_i.between?(0, 60) || !value['seconds'].to_i.between?(0, 60)
      @errors << "#{response_field.label} isn't a valid time."
    end
  end
end