class Mutations::HashFilter

Attributes

optional_inputs[RW]
required_inputs[RW]

Public Class Methods

new(opts = {}, &block) click to toggle source
Calls superclass method
# File lib/mutations/hash_filter.rb, line 16
def initialize(opts = {}, &block)
  super(opts)

  @optional_inputs = {}
  @required_inputs = {}
  @current_inputs = @required_inputs

  if block_given?
    instance_eval(&block)
  end
end
register_additional_filter(type_class, type_name) click to toggle source
# File lib/mutations/hash_filter.rb, line 3
def self.register_additional_filter(type_class, type_name)
  define_method(type_name) do |name, options = {}, &block|
    @current_inputs[name.to_sym] = type_class.new(options, &block)
  end
end

Public Instance Methods

array(name, options = {}, &block) click to toggle source
# File lib/mutations/hash_filter.rb, line 65
def array(name, options = {}, &block)
  name_sym = name.to_sym
  @current_inputs[name.to_sym] = ArrayFilter.new(name_sym, options, &block)
end
dup() click to toggle source
# File lib/mutations/hash_filter.rb, line 28
def dup
  dupped = HashFilter.new
  @optional_inputs.each_pair do |k, v|
    dupped.optional_inputs[k] = v
  end
  @required_inputs.each_pair do |k, v|
    dupped.required_inputs[k] = v
  end
  dupped
end
filter(data) click to toggle source
# File lib/mutations/hash_filter.rb, line 70
def filter(data)

  # Handle nil case
  if data.nil?
    return [nil, nil] if options[:nils]
    return [nil, :nils]
  end

  # Ensure it's a hash
  return [data, :hash] unless data.respond_to?(:to_hash)

  # We always want a hash with indifferent access
  unless data.is_a?(HashWithIndifferentAccess)
    data = data.to_hash.with_indifferent_access
  end

  errors = ErrorHash.new
  filtered_data = HashWithIndifferentAccess.new
  wildcard_filterer = nil

  [[@required_inputs, true], [@optional_inputs, false]].each do |(inputs, is_required)|
    inputs.each_pair do |key, filterer|

      # If we are doing wildcards, then record so and move on
      if key == :*
        wildcard_filterer = filterer
        next
      end

      data_element = data[key]

      if data.has_key?(key)
        sub_data, sub_error = filterer.filter(data_element)

        if sub_error.nil?
          filtered_data[key] = sub_data
        elsif !is_required && filterer.discard_invalid?
          data.delete(key)
        elsif !is_required && sub_error == :empty && filterer.discard_empty?
          data.delete(key)
        elsif !is_required && sub_error == :nils && filterer.discard_nils?
          data.delete(key)
        else
          error_key = filterer.options[:error_key] || key
          sub_error = ErrorAtom.new(error_key, sub_error) if sub_error.is_a?(Symbol)
          errors[key] = sub_error
        end
      end

      if !data.has_key?(key)
        if filterer.has_default?
          filtered_data[key] = filterer.default
        elsif is_required
          error_key = filterer.options[:error_key] || key
          errors[key] = ErrorAtom.new(error_key, :required)
        end
      end
    end
  end

  if wildcard_filterer
    filtered_keys = data.keys - filtered_data.keys

    filtered_keys.each do |key|
      data_element = data[key]

      sub_data, sub_error = wildcard_filterer.filter(data_element)
      if sub_error.nil?
        filtered_data[key] = sub_data
      elsif wildcard_filterer.discard_invalid?
        data.delete(key)
      elsif sub_error == :empty && wildcard_filterer.discard_empty?
        data.delete(key)
      elsif sub_error == :nils && wildcard_filterer.discard_nils?
        data.delete(key)
      else
        sub_error = ErrorAtom.new(key, sub_error) if sub_error.is_a?(Symbol)
        errors[key] = sub_error
      end
    end
  end

  if errors.any?
    [data, errors]
  else
    [filtered_data, nil]     # We win, it's valid!
  end
end
hash(name, options = {}, &block) click to toggle source
# File lib/mutations/hash_filter.rb, line 57
def hash(name, options = {}, &block)
  @current_inputs[name.to_sym] = HashFilter.new(options, &block)
end
model(name, options = {}) click to toggle source
# File lib/mutations/hash_filter.rb, line 61
def model(name, options = {})
  @current_inputs[name.to_sym] = ModelFilter.new(name.to_sym, options)
end
optional(&block) click to toggle source
# File lib/mutations/hash_filter.rb, line 44
def optional(&block)
  @current_inputs = @optional_inputs
  instance_eval(&block)
end
optional_keys() click to toggle source
# File lib/mutations/hash_filter.rb, line 53
def optional_keys
  @optional_inputs.keys
end
required(&block) click to toggle source
# File lib/mutations/hash_filter.rb, line 39
def required(&block)
  @current_inputs = @required_inputs
  instance_eval(&block)
end
required_keys() click to toggle source
# File lib/mutations/hash_filter.rb, line 49
def required_keys
  @required_inputs.keys
end