Skip to content

Commit 0946bf8

Browse files
feat(validation.md): added custom validator documentation (#1016)
I created a [PR](vapor/vapor#3263) earlier today, adding in a custom validator called `Custom`. This allows users to easily create custom validations, it is simpler to use and shorter in syntax compared to the current [Custom Validators](https://docs.vapor.codes/basics/validation/#custom-validators). This PR also resolves [this issue](#1015) --------- Co-authored-by: Tim Condon <[email protected]>
1 parent a0d7615 commit 0946bf8

File tree

2 files changed

+48
-48
lines changed

2 files changed

+48
-48
lines changed

docs/basics/errors.md

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -136,51 +136,6 @@ struct MyError: DebuggableError {
136136

137137
`DebuggableError` has several other properties like `possibleCauses` and `suggestedFixes` that you can use to improve the debuggability of your errors. Take a look at the protocol itself for more information.
138138

139-
## Stack Traces
140-
141-
Vapor includes support for viewing stack traces for both normal Swift errors and crashes.
142-
143-
### Swift Backtrace
144-
145-
Vapor uses the [SwiftBacktrace](https://github.com/swift-server/swift-backtrace) library to provide stack traces after a fatal error or assertion on Linux. In order for this to work, your app must include debug symbols during compilation.
146-
147-
```sh
148-
swift build -c release -Xswiftc -g
149-
```
150-
151-
### Error Traces
152-
153-
By default, `Abort` will capture the current stack trace when initialized. Your custom error types can achieve this by conforming to `DebuggableError` and storing `StackTrace.capture()`.
154-
155-
```swift
156-
import Vapor
157-
158-
struct MyError: DebuggableError {
159-
var identifier: String
160-
var reason: String
161-
var stackTrace: StackTrace?
162-
163-
init(
164-
identifier: String,
165-
reason: String,
166-
stackTrace: StackTrace? = .capture()
167-
) {
168-
self.identifier = identifier
169-
self.reason = reason
170-
self.stackTrace = stackTrace
171-
}
172-
}
173-
```
174-
175-
When your application's [log level](logging.md#level) is set to `.debug` or lower, error stack traces will be included in log output.
176-
177-
Stack traces will not be captured when the log level is greater than `.debug`. To override this behavior, set `StackTrace.isCaptureEnabled` manually in `configure`.
178-
179-
```swift
180-
// Always capture stack traces, regardless of log level.
181-
StackTrace.isCaptureEnabled = true
182-
```
183-
184139
## Error Middleware
185140

186141
`ErrorMiddleware` is one of the only two middlewares added to your application by default. This middleware converts Swift errors that have been thrown or returned by your route handlers into HTTP responses. Without this middleware, errors thrown will result in the connection being closed without a response.

docs/basics/validation.md

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Validation
22

3-
Vapor's Validation API helps you validate incoming request before using the [Content](content.md) API to decode data.
3+
Vapor's Validation API helps you validate the body and query parameters of an incoming request before using the [Content](content.md) API to decode data.
44

55
## Introduction
66

@@ -219,8 +219,9 @@ Below is a list of the currently supported validators and a brief explanation of
219219
|`.nil`|Value is `null`.|
220220
|`.range(_:)`|Value is within supplied `Range`.|
221221
|`.url`|Contains a valid URL.|
222+
|`.custom(_:, validationClosure: (value) -> Bool)`|Custom, once-off validation.|
222223

223-
Validators can also be combined to build complex validations using operators.
224+
Validators can also be combined to build complex validations using operators. More information on `.custom` validator at [[#Custom Validators]].
224225

225226
|Operator|Position|Description|
226227
|-|-|-|
@@ -232,7 +233,11 @@ Validators can also be combined to build complex validations using operators.
232233

233234
## Custom Validators
234235

235-
Creating a custom validator for zip codes allows you to extend the functionality of the validation framework. In this section, we'll walk you through the steps to create a custom validator for validating zip codes.
236+
There are two ways to create custom validators.
237+
238+
### Extending Validation API
239+
240+
Extending the Validation API is best suited for cases where you plan on using the custom validator in more than one `Content` object. In this section, we'll walk you through the steps to create a custom validator for validating zip codes.
236241

237242
First create a new type to represent the `ZipCode` validation results. This struct will be responsible for reporting whether a given string is a valid zip code.
238243

@@ -289,4 +294,44 @@ Now that you've defined the custom `zipCode` validator, you can use it to valida
289294
```swift
290295
validations.add("zipCode", as: String.self, is: .zipCode)
291296
```
297+
### `Custom` Validator
298+
299+
The `Custom` validator is best suited for cases where you want to validate a property in only one `Content` object. This implementation has the following two advantages compared to extending the Validation API:
300+
301+
- Simpler to implement custom validation logic.
302+
- Shorter syntax.
303+
304+
In this section, we'll walk you through the steps to create a custom validator for checking whether an employee is part of our company by looking at the `nameAndSurname` property.
292305

306+
```swift
307+
let allCompanyEmployees: [String] = [
308+
"Everett Erickson",
309+
"Sabrina Manning",
310+
"Seth Gates",
311+
"Melina Hobbs",
312+
"Brendan Wade",
313+
"Evie Richardson",
314+
]
315+
316+
struct Employee: Content {
317+
var nameAndSurname: String
318+
var email: String
319+
var age: Int
320+
var role: String
321+
322+
static func validations(_ validations: inout Validations) {
323+
validations.add(
324+
"nameAndSurname",
325+
as: String.self,
326+
is: .custom("Validates whether employee is part of XYZ company by looking at name and surname.") { nameAndSurname in
327+
for employee in allCompanyEmployees {
328+
if employee == nameAndSurname {
329+
return true
330+
}
331+
}
332+
return false
333+
}
334+
)
335+
}
336+
}
337+
```

0 commit comments

Comments
 (0)