class Hamster::Hash

Public Instance Methods

schema_walk(value, mapper) click to toggle source
# File lib/rschema_hamster/hamster_ext.rb, line 51
def schema_walk(value, mapper)
  return RSchema::ErrorDetails.new(value, 'is not a Hash') if not value.is_a?(Hamster::Hash)

  # extract details from the schema
  required_keys = Set.new
  all_subschemas = {}
  each do |(k, subschema)|
    if k.is_a?(RSchema::OptionalHashKey)
      all_subschemas[k.key] = subschema
    else
      required_keys << k
      all_subschemas[k] = subschema
    end
  end

  # check for extra keys that shouldn't be there
  extraneous = value.keys.reject{ |k| all_subschemas.has_key?(k) }
  if extraneous.size > 0
    return RSchema::ErrorDetails.new(value, "has extraneous keys: #{extraneous.to_a.inspect}")
  end

  # check for required keys that are missing
  missing_requireds = required_keys.reject{ |k| value.has_key?(k) }
  if missing_requireds.size > 0
    return RSchema::ErrorDetails.new(value, "is missing required keys: #{missing_requireds.to_a.inspect}")
  end

  # walk the subvalues
  value.reduce(Hamster.hash) do |accum, (k, subvalue)|
    # puts "RSchema.walk(all_subschemas[k], subvalue, mapper) all_subschemas[#{k.inspect}]: #{all_subschemas[k].inspect}, subvalue: (#{subvalue.class}) #{subvalue.inspect}"
    subvalue_walked, error = RSchema.walk(all_subschemas[k], subvalue, mapper)
    # puts "  => subvalue_walked: (#{subvalue_walked.class}) #{subvalue_walked.inspect}, error: #{error.inspect}"
    break error.extend_key_path(k) if error
    a = accum.put(k, subvalue_walked)
    # puts "  (accum: #{accum.inspect})"
    a
  end
end