Class: Stannum::Constraints::Hashes::ExtraKeys

Inherits:
Base
  • Object
show all
Defined in:
lib/stannum/constraints/hashes/extra_keys.rb

Overview

Constraint for validating the keys of a hash-like object.

When using this constraint, the keys must be strings or symbols, and the hash keys must be of the same type. A constraint configured with string keys will not match a hash with symbol keys, and vice versa.

Examples:

keys       = %i[fuel mass size]
constraint = Stannum::Constraints::Hashes::ExpectedKeys.new(keys)

constraint.matches?({})                                #=> true
constraint.matches?({ fuel: 'Monopropellant' })        #=> true
constraint.matches?({ 'fuel' => 'Monopropellant' })    #=> false
constraint.matches?({ electric: true, fuel: 'Xenon' }) #=> false
constraint.matches?({ fuel: 'LF/O', mass: '1 ton', size: 'Medium' })
#=> true
constraint.matches?(
  { fuel: 'LF', mass: '2 tons', nuclear: true, size: 'Medium' }
)
#=> false

Constant Summary collapse

NEGATED_TYPE =

The :type of the error generated for a matching object.

'stannum.constraints.hashes.no_extra_keys'
TYPE =

The :type of the error generated for a non-matching object.

'stannum.constraints.hashes.extra_keys'

Instance Attribute Summary

Attributes inherited from Base

#options

Instance Method Summary collapse

Methods inherited from Base

#==, #clone, #dup, #match, #message, #negated_errors_for, #negated_match, #negated_message, #negated_type, #type, #with_options

Constructor Details

#initialize(expected_keys, **options) ⇒ ExtraKeys

Returns a new instance of ExtraKeys.

Parameters:

  • expected_keys (Array, Proc)

    The expected keys. If a Proc, will be evaluated each time the constraint is matched.

  • options (Hash<Symbol, Object>)

    Configuration options for the constraint. Defaults to an empty Hash.



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/stannum/constraints/hashes/extra_keys.rb', line 38

def initialize(expected_keys, **options)
  validate_expected_keys(expected_keys)

  expected_keys =
    if expected_keys.is_a?(Array)
      Set.new(expected_keys)
    else
      expected_keys
    end

  super(expected_keys: expected_keys, **options)
end

Instance Method Details

#does_not_match?(actual) ⇒ true, false

Returns true if the object responds to #[] and #keys and the object has at least one key that is not in expected_keys.

Returns:

  • (true, false)

    true if the object responds to #[] and #keys and the object has at least one key that is not in expected_keys.



53
54
55
56
57
# File 'lib/stannum/constraints/hashes/extra_keys.rb', line 53

def does_not_match?(actual)
  return false unless hash?(actual)

  !(Set.new(actual.keys) <= expected_keys) # rubocop:disable Style/InverseMethods
end

#errors_for(actual, errors: nil) ⇒ Stannum::Errors

Note:

This method should only be called for an object that does not match the constraint. Generating errors for a matching object can result in undefined behavior.

Generates an errors object for the given object.

The errors object represents the difference between the given object and the expected properties or behavior. It may be the same for all objects, or different based on the details of the object or the constraint.

Examples:

Generating errors for a non-matching object.

constraint = CustomConstraint.new
object     = NonMatchingObject.new
errors     = constraint.errors_for(object)

errors.class #=> Stannum::Errors
errors.to_a  #=> [{ type: 'some_error', message: 'some error message' }]

Parameters:

  • actual (Object)

    The object to generate errors for.

  • errors (Stannum::Errors) (defaults to: nil)

    The errors object to append errors to. If an errors object is not given, a new errors object will be created.

Returns:

See Also:



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/stannum/constraints/hashes/extra_keys.rb', line 60

def errors_for(actual, errors: nil)
  errors ||= Stannum::Errors.new

  unless actual.respond_to?(:keys)
    return add_invalid_hash_error(actual: actual, errors: errors)
  end

  each_extra_key(actual) do |key, value|
    key = Stannum::Support::Coercion.error_key(key)

    errors[key].add(type, value: value)
  end

  errors
end

#expected_keysSet

Returns the expected keys.

Returns:

  • (Set)

    the expected keys.



77
78
79
80
81
82
83
# File 'lib/stannum/constraints/hashes/extra_keys.rb', line 77

def expected_keys
  keys = options[:expected_keys]

  return keys unless keys.is_a?(Proc)

  Set.new(keys.call)
end

#matches?(actual) ⇒ true, false Also known as: match?

Returns true if the object responds to #[] and #keys and the object does not have any key that is not in expected_keys.

Returns:

  • (true, false)

    true if the object responds to #[] and #keys and the object does not have any key that is not in expected_keys.



87
88
89
90
91
# File 'lib/stannum/constraints/hashes/extra_keys.rb', line 87

def matches?(actual)
  return false unless actual.respond_to?(:keys)

  Set.new(actual.keys) <= expected_keys
end