Skip to content

Commit

Permalink
Merge pull request #6 from 64J0/64J0-patch-1
Browse files Browse the repository at this point in the history
chore: improve docs/spec.md
  • Loading branch information
stijnmoreels committed Mar 20, 2024
2 parents 5e6cf6e + 9e32d37 commit 54f3299
Showing 1 changed file with 42 additions and 6 deletions.
48 changes: 42 additions & 6 deletions docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
The `FPrimitive` library contains a way to describe how domain models should look like by specifiying **specifications**.
These specifications are a set of requirements that sets how a set of values should look like.

> The return type is always a `Result<_, _>` where the `Error` is a `Map<_, _>` where the errors are grouped together (more on this later).
> The return type is always a `Result<_, _>` where the `Error` is a `Map<_, _>` and the errors are grouped together (more on this later).
For example, a model that only can contain positie numbers could be described as:
For example, a model that only can contain positive numbers could be described as:

```fsharp
type PositiveInt =
Expand All @@ -15,7 +15,7 @@ type PositiveInt =
else Error "integer should be greater than zero"
```

When things start to get complicated, above approach can get really complicated and overly complex to maintain.
When things start to get complicated, above approach can get really messy and overly complex to maintain.
That's where this library can help with (following sample shows the same functionality implemented with the library).

```fsharp
Expand Down Expand Up @@ -45,7 +45,7 @@ Spec.Of<int>()
```

Then, additional requirements can be added for that type. See the API reference of the `Spec` module for all the available built-in requirements.
Each requirement will require an error message that all will be used when the validation fails.
Each requirement will require an error message that will be used when the validation fails.

```fsharp
// F#
Expand All @@ -66,7 +66,7 @@ Spec.Of<int>()

## Validate Your Specification

When you want to validate an incoming value with your specification, there are several ways to do this:
When you want to validate an incoming value with your specification, there are several ways to do it:

```fsharp
// F#
Expand Down Expand Up @@ -179,7 +179,7 @@ let (x : Result<int option, _>) = specModel Some 5 {
greaterThanOrEqualOf id 0 "should be greater than zero" }
```

## Advanced Example
## Advanced Examples

Following sample shows how a ISBN13 book number can be expressed with specifications:

Expand All @@ -204,4 +204,40 @@ type ISBN13 =
startsWith "987" "ISBN13 number should start with '987'"
matches pattern (sprintf "ISBN13 number should match regular expression: %s" pattern)
verify checksum "ISBN13 @checksum was invalid" }
```

And here is a sample `fsx` script for e-mail validation based on this [.NET documentation](https://learn.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format#example):

```fsharp
#r "nuget: FPrimitive, 3.2.2"
open FPrimitive
type Email =
private
| Email of string
static member create x =
let pattern = @"^[^@\s]+@[^@\s]+\.[^@\s]+$"
specModel Email x {
tag "email"
notNullOrWhiteSpace "Email should not be blank!"
stringNotContains " " "E-mail should not contain empty spaces!"
matches pattern "Invalid e-mail!"
}
// tests
[ "[email protected]"
"[email protected] "
"test@[email protected]"
"[email protected]"
""
"[email protected]" ]
|> List.map (Email.create)
|> List.iter (fun result ->
match result with
| Ok r -> printfn $"Ok result: {r}"
| Error r -> eprintfn $"Error result: {r}")
```

0 comments on commit 54f3299

Please sign in to comment.