Skip to content

Support custom explains #7

Description

@jeme

It should be possible to give rules a custom explanation.

Starting with considering the root, there is multiple ways to provide this syntactically, e.g.

// Option 1:
When("name", Is.Defined())
  .Then(It, Must.Be.String() & Have.MaxLength(256), "when name is provided, name must be a string and be max 256 characters long");

// Option 2:
When("name", Is.Defined())
  .Then(It, Must.Be.String() & Have.MaxLength(256))
  .Explain("when name is provided, name must be a string and be max 256 characters long");

If possible, the ability to give partial explanations may also be interesting, here option 2 are probably likely to be easier to implement as it allows for a more generic pattern in general and wrapper rules etc.

This could then be allowed to use on any construct in the framework from a single constraint to grouped constraints, field rules and all the way up to the when.

// Option 1:
When("name", Is.Defined())
  .Then(It, Must.Be.String() & Have.MaxLength(256, "max 256 characters"));

// Option 2:
When("name", Is.Defined())
  .Then(It, Must.Be.String() & Have.MaxLength(256).Explain("max 256 characters"));

Although this raises the question on how these should interact with each other in cases where custom explains has been attacked both at a outer and inner level.

// Option 2:
When("name", Is.Defined())
  .Then(It, Must.Be.String() & Have.MaxLength(256).Explain("max 256 characters"))
  .Explain("must be a string and be max 256 characters long");
// ???

Another challenge is that we can actually rationalize about which rules we should display to the user during validations when it fails.

E.g. given the object: { name: "John", surname: "Doe", age: 500 }

When(Any)
  .Then(Field("name", Must.Match("^[A-Za-z]*$")
      & Field("surname", Must.Match("^[A-Za-z]*$")
      & Field("age", Must.Be.Between(0, 150));

We can actually settle for displaying the failed "age" constraint rather than all of them, but this becomes tricky given a custom explanation. We can give a general rule that just says it will go as deep as it can until it hits a custom explanation and then it uses that, then the following would work reasonably:

When(Any)
  .Then(Field("name", Must.Match("^[A-Za-z]*$")).Explain("name must consist of alphabetic characters only")
      & Field("surname", Must.Match("^[A-Za-z]*$")).Explain("surname must consist of alphabetic characters only")
      & Field("age", Must.Be.Between(0, 150)).Explain("age must be a positive number and max 150"));

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions