module Athena::Validator::Constraints::GroupSequence::Provider

Overview

AVD::Constraints::GroupSequences can be a good way to create efficient validations. However, since the sequence is static, it is not a very flexible solution.

Group sequence providers allow the sequence to be dynamically determined at runtime. This allows running specific validations only when the object is in a specific state, such as validating a "registered" user differently than a non-registered user.

class User
  include AVD::Validatable

  # Include the interface that informs the validator this object will provide its sequence.
  include AVD::Constraints::GroupSequence::Provider

  @[Assert::NotBlank]
  property name : String

  # Only validate the `email` property if the `#group_sequence` method includes "registered"
  # Which can be determined using the current state of the object.
  @[Assert::Email(groups: "registered")]
  @[Assert::NotBlank(groups: "registered")]
  property email : String?

  def initialize(@name : String, @email : String); end

  # Define a method that returns the sequence.
  def group_sequence : Array(String | Array(String)) | AVD::Constraints::GroupSequence
    # When returning a 1D array, if there is a vaiolation in any group
    # the rest of the groups are not validated.  E.g. if `User` fails,
    # `registered` and `api` are not validated:
    return ["User", "registered", "api"]

    # When returning a nested array, all groups included in each array are validated.
    # E.g. if `User` fails, `Premium` is also validated (and you'll get its violations),
    # but `api` will not be validated
    return [["User", "registered"], "api"]
  end
end

See AVD::Constraints::Sequentially for a more straightforward method of applying constraints sequentially on a single property.

Direct including types

Defined in:

constraints/group_sequence.cr

Instance Method Summary

Instance Method Detail

abstract def group_sequence : Array(String | Array(String)) | AVD::Constraints::GroupSequence #

[View source]