Class: Stannum::Constraints::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/stannum/constraints/base.rb

Overview

A constraint codifies a particular expectation about an object.

Defined Under Namespace

Classes: Builder

Constant Summary collapse

NEGATED_TYPE =

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

'stannum.constraints.valid'
TYPE =

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

'stannum.constraints.invalid'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Base

Returns a new instance of Base.

Parameters:

  • options (Hash<Symbol, Object>)

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

Options Hash (**options):

  • :message (String)

    The default error message generated for a non-matching object.

  • :negated_message (String)

    The default error message generated for a matching object.

  • :negated_type (String)

    The type of the error generated for a matching object.

  • :type (String)

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



33
34
35
# File 'lib/stannum/constraints/base.rb', line 33

def initialize(**options)
  self.options = options
end

Instance Attribute Details

#optionsHash<Symbol, Object>

Returns Configuration options for the constraint.

Returns:

  • (Hash<Symbol, Object>)

    Configuration options for the constraint.



38
39
40
# File 'lib/stannum/constraints/base.rb', line 38

def options
  @options
end

Instance Method Details

#==(other) ⇒ true, false

Performs an equality comparison.

Parameters:

  • other (Object)

    The object to compare.

Returns:

  • (true, false)

    true if the other object has the same class and options; otherwise false.



46
47
48
# File 'lib/stannum/constraints/base.rb', line 46

def ==(other)
  other.class == self.class && options == other.options
end

#clone(freeze: nil) ⇒ Stannum::Constraints::Base

Produces a shallow copy of the constraint.

Parameters:

  • freeze (true, false, nil) (defaults to: nil)

    If true or false, sets the frozen status of the cloned constraint; otherwise, copies the frozen status of the original. Defaults to nil.

Returns:



57
58
59
60
61
# File 'lib/stannum/constraints/base.rb', line 57

def clone(freeze: nil)
  freeze = true if freeze.nil? && RUBY_VERSION <= '3.0.0'

  super(freeze: freeze).copy_properties(self)
end

#does_not_match?(actual) ⇒ true, false

Checks that the given object does not match the constraint.

Examples:

Checking a matching object.

constraint = CustomConstraint.new
object     = MatchingObject.new

constraint.does_not_match?(object) #=> false

Checking a non-matching object.

constraint = CustomConstraint.new
object     = NonMatchingObject.new

constraint.does_not_match?(object) #=> true

Parameters:

  • actual (Object)

    The object to match.

Returns:

  • (true, false)

    false if the object matches the expected properties or behavior, otherwise true.

See Also:



83
84
85
# File 'lib/stannum/constraints/base.rb', line 83

def does_not_match?(actual)
  !matches?(actual)
end

#dupStannum::Constraints::Base

Produces a shallow copy of the constraint.

Returns:



90
91
92
# File 'lib/stannum/constraints/base.rb', line 90

def dup
  super.copy_properties(self)
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:



120
121
122
# File 'lib/stannum/constraints/base.rb', line 120

def errors_for(actual, errors: nil) # rubocop:disable Lint/UnusedMethodArgument
  (errors || Stannum::Errors.new).add(type, message: message)
end

#match(actual) ⇒ Object

Checks the given object against the constraint and returns errors, if any.

This method checks the given object against the expected properties or behavior. If the object matches the constraint, #match will return true. If the object does not match the constraint, #match will return false and the generated errors for that object.

Examples:

Checking a matching object.

constraint = CustomConstraint.new
object     = MatchingObject.new

success, errors = constraint.match(object)
success #=> true
errors  #=> nil

Checking a non-matching object.

constraint = CustomConstraint.new
object     = NonMatchingObject.new

success, errors = constraint.match(object)
success      #=> false
errors.class #=> Stannum::Errors
errors.to_a  #=> [{ type: 'some_error', message: 'some error message' }]

Parameters:

  • actual (Object)

    The object to match.

See Also:



152
153
154
155
156
# File 'lib/stannum/constraints/base.rb', line 152

def match(actual)
  return [true, Stannum::Errors.new] if matches?(actual)

  [false, errors_for(actual)]
end

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

Examples:

Checking a matching object.

constraint = CustomConstraint.new
object     = MatchingObject.new

constraint.matches?(object) #=> true

Checking a non-matching object.

constraint = CustomConstraint.new
object     = NonMatchingObject.new

constraint.matches?(object) #=> false

Checks that the given object matches the constraint.

Parameters:

  • actual (Object)

    The object to match.

Returns:

  • (true, false)

    true if the object matches the expected properties or behavior, otherwise false.

See Also:



179
180
181
# File 'lib/stannum/constraints/base.rb', line 179

def matches?(_actual)
  false
end

#messageString?

Returns the default error message generated for a non-matching object.

Returns:

  • (String, nil)

    the default error message generated for a non-matching object.



186
187
188
# File 'lib/stannum/constraints/base.rb', line 186

def message
  options[:message]
end

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

Note:

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

Generates an errors object for the given object when negated.

The errors object represents the difference between the given object and the expected properties or behavior when the constraint is negated. 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 matching object.

constraint = CustomConstraint.new
object     = MatchingObject.new
errors     = constraint.negated_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:



217
218
219
220
# File 'lib/stannum/constraints/base.rb', line 217

def negated_errors_for(actual, errors: nil) # rubocop:disable Lint/UnusedMethodArgument
  (errors || Stannum::Errors.new)
    .add(negated_type, message: negated_message)
end

#negated_match(actual) ⇒ Object

Checks the given object against the constraint and returns errors, if any.

This method checks the given object against the expected properties or behavior. If the object matches the constraint, #negated_match will return false and the generated errors for that object. If the object does not match the constraint, #negated_match will return true.

Examples:

Checking a matching object.

constraint = CustomConstraint.new
object     = MatchingObject.new

success, errors = constraint.negated_match(object)
success      #=> false
errors.class #=> Stannum::Errors
errors.to_a  #=> [{ type: 'some_error', message: 'some error message' }]

Checking a non-matching object.

constraint = CustomConstraint.new
object     = NonMatchingObject.new

success, errors = constraint.negated_match(object)
success #=> true
errors  #=> nil

Parameters:

  • actual (Object)

    The object to match.

See Also:



251
252
253
254
255
# File 'lib/stannum/constraints/base.rb', line 251

def negated_match(actual)
  return [true, Stannum::Errors.new] if does_not_match?(actual)

  [false, negated_errors_for(actual)]
end

#negated_messageString?

Returns The default error message generated for a matching object.

Returns:

  • (String, nil)

    The default error message generated for a matching object.



259
260
261
# File 'lib/stannum/constraints/base.rb', line 259

def negated_message
  options[:negated_message]
end

#negated_typeString

Returns the error type generated for a matching object.

Returns:

  • (String)

    the error type generated for a matching object.



264
265
266
# File 'lib/stannum/constraints/base.rb', line 264

def negated_type
  options.fetch(:negated_type, self.class::NEGATED_TYPE)
end

#typeString

Returns the error type generated for a non-matching object.

Returns:

  • (String)

    the error type generated for a non-matching object.



269
270
271
# File 'lib/stannum/constraints/base.rb', line 269

def type
  options.fetch(:type, self.class::TYPE)
end

#with_options(**options) ⇒ Stannum::Constraints::Base

Creates a copy of the constraint and updates the copy’s options.

Parameters:

  • options (Hash)

    The options to update.

Returns:



278
279
280
# File 'lib/stannum/constraints/base.rb', line 278

def with_options(**options)
  dup.copy_properties(self, options: self.options.merge(options))
end