class InputSanitizer::V1::Sanitizer

Public Class Methods

clean(data) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 9
def self.clean(data)
  new(data).cleaned
end
converters() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 36
def self.converters
  {
    :integer => InputSanitizer::V1::IntegerConverter.new,
    :string => InputSanitizer::V1::StringConverter.new,
    :date => InputSanitizer::V1::DateConverter.new,
    :time => InputSanitizer::V1::TimeConverter.new,
    :boolean => InputSanitizer::V1::BooleanConverter.new,
    :integer_or_blank => InputSanitizer::V1::IntegerConverter.new.extend(InputSanitizer::V1::AllowNil),
    :string_or_blank => InputSanitizer::V1::StringConverter.new.extend(InputSanitizer::V1::AllowNil),
    :date_or_blank => InputSanitizer::V1::DateConverter.new.extend(InputSanitizer::V1::AllowNil),
    :time_or_blank => InputSanitizer::V1::TimeConverter.new.extend(InputSanitizer::V1::AllowNil),
    :boolean_or_blank => InputSanitizer::V1::BooleanConverter.new.extend(InputSanitizer::V1::AllowNil),
  }
end
custom(*keys) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 67
def self.custom(*keys)
  options = keys.pop
  converter = options.delete(:converter)
  keys.push(options)
  raise "You did not define a converter for a custom type" if converter == nil
  self.set_keys_to_converter(keys, converter)
end
inherited(subclass) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 51
def self.inherited(subclass)
  subclass.fields = self.fields.dup
end
initialize_types_dsl() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 55
  def self.initialize_types_dsl
    converters.keys.each do |name|
      class_eval <<-END
        def self.#{name}(*keys)
          set_keys_to_converter(keys, :#{name})
        end
      END
    end
  end
nested(*keys) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 75
def self.nested(*keys)
  options = keys.pop
  sanitizer = options.delete(:sanitizer)
  keys.push(options)
  raise "You did not define a sanitizer for nested value" if sanitizer == nil
  converter = lambda { |value|
    instance = sanitizer.new(value)
    raise InputSanitizer::ConversionError.new(instance.errors) unless instance.valid?
    instance.cleaned
  }

  keys << {} unless keys.last.is_a?(Hash)
  keys.last[:nested] = true

  self.set_keys_to_converter(keys, converter)
end
new(data) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 2
def initialize(data)
  @data = symbolize_keys(data)
  @performed = false
  @errors = []
  @cleaned = InputSanitizer::RestrictedHash.new(self.class.fields.keys)
end

Protected Class Methods

fields() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 93
def self.fields
  @fields ||= {}
end
fields=(new_fields) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 97
def self.fields=(new_fields)
  @fields = new_fields
end

Private Class Methods

extract_options!(array) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 102
def self.extract_options!(array)
  array.last.is_a?(Hash) ? array.pop : {}
end
set_keys_to_converter(keys, converter_or_type) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 151
def self.set_keys_to_converter(keys, converter_or_type)
  options = extract_options!(keys)
  converter = if converter_or_type.is_a?(Symbol)
    converters[converter_or_type]
  else
    converter_or_type
  end

  keys.each do |key|
    fields[key] = {
      :converter => converter,
      :options => options
    }
  end
end

Public Instance Methods

[](field) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 13
def [](field)
  cleaned[field]
end
cleaned() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 17
def cleaned
  return @cleaned if @performed

  perform_clean

  @performed = true
  @cleaned.freeze
end
errors() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 31
def errors
  cleaned
  @errors
end
valid?() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 26
def valid?
  cleaned
  @errors.empty?
end

Private Instance Methods

add_error(field, error_type, value, description = nil) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 132
def add_error(field, error_type, value, description = nil)
  @errors << {
    :field => field,
    :type => error_type,
    :value => value,
    :description => description
  }
end
clean_field(field, hash) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 110
def clean_field(field, hash)
  if hash[:options][:nested] && @data.has_key?(field)
    if hash[:options][:collection]
      raise InputSanitizer::ConversionError.new("expected an array") unless @data[field].is_a?(Array)
    else
      raise InputSanitizer::ConversionError.new("expected a hash") unless @data[field].is_a?(Hash)
    end
  end

  @cleaned[field] = InputSanitizer::V1::CleanField.call(hash[:options].merge({
    :has_key => @data.has_key?(field),
    :data => @data[field],
    :converter => hash[:converter],
    :provide => @data[hash[:options][:provide]],
  }))
rescue InputSanitizer::ConversionError => error
  add_error(field, :invalid_value, @data[field], error.message)
rescue InputSanitizer::ValueMissingError => error
  add_error(field, :missing, nil, nil)
rescue InputSanitizer::OptionalValueOmitted
end
perform_clean() click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 106
def perform_clean
  self.class.fields.each { |field, hash| clean_field(field, hash) }
end
symbolize_keys(data) click to toggle source
# File lib/input_sanitizer/v1/sanitizer.rb, line 141
def symbolize_keys(data)
  symbolized_hash = {}

  data.each do |key, value|
    symbolized_hash[key.to_sym] = value
  end

  symbolized_hash
end