Skip to content

Commit da8ceed

Browse files
Document default spec-specific phrasers and phraser matching order
1 parent d8fcd38 commit da8ceed

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,102 @@ It's certainly useful to have a default phraser which is used whenever no matchi
147147

148148
You can remove the default phraser by calling `(remove-default!)`.
149149

150+
#### Default Phraser for a Spec
151+
152+
It is possible to combine `:default` and `:via` to produce a default phraser for a spec. This can be used to avoid having to deal with every possible failure case. It also works as a fallback that catches cases that were missed (e.g. after spec change) or maybe intentionally ignored as they are hard to phrase.
153+
154+
For example spec
155+
156+
```clojure
157+
(s/def ::vector-with-sum-8
158+
(s/and vector?
159+
#(every? number? %)
160+
#(= 8 (reduce + 0 %))))
161+
```
162+
163+
can be covered using a single default phraser
164+
165+
```clojure
166+
(defphraser :default
167+
{:via [::vector-with-sum-8]}
168+
[_ _]
169+
"This should be a vector of numbers with sum 8.")
170+
```
171+
172+
that ensures that `"This should be a vector of numbers with sum 8."` is returned on any error.
173+
174+
```clojure
175+
(phrase-first {} ::vector-with-sum-8 {1 2 "3" "4"})
176+
;;=> "This should be a vector of numbers with sum 8."
177+
178+
(phrase-first {} ::vector-with-sum-8 [1 2 "3" 4])
179+
;;=> "This should be a vector of numbers with sum 8."
180+
181+
(phrase-first {} ::vector-with-sum-8 [1 2 3 4])
182+
;;=> "This should be a vector of numbers with sum 8."
183+
184+
```
185+
186+
### Phraser Priority Order
187+
188+
A single "best match" phraser is used to produce a phrase for any single spec problem. This "best match" phraser is currently found based on priority
189+
190+
1. `:pred` + `:via` phraser
191+
1. `:default` + `:via` phraser
192+
1. `:pred` phraser
193+
1. `:default` phraser
194+
195+
and `:via` length. A phraser with `:via` matching a longer suffix of problem's `:via` takes precedence over a phraser with a shorter match or no `:via`.
196+
197+
For example for spec
198+
199+
```clojure
200+
(s/def ::vector-with-sum-8
201+
(s/and vector?
202+
#(every? number? %)
203+
#(= 8 (reduce + 0 %))))
204+
```
205+
206+
phraser
207+
208+
```
209+
(defphraser :default
210+
{:via [::vector-with-sum-8]}
211+
[_ _]
212+
"This should be a vector of numbers with sum 8.")
213+
```
214+
215+
takes precedence over
216+
217+
```clojure
218+
(defphraser #(every? number? %)
219+
[_ _]
220+
"Every item should be a number.")
221+
```
222+
223+
like this.
224+
225+
```clojure
226+
(phrase-first {} ::vector-with-sum-8 [1 2 "3" 4])
227+
;;=> "This should be a vector of numbers with sum 8."
228+
```
229+
230+
However, phraser
231+
232+
```clojure
233+
(defphraser #(every? number? %)
234+
{:via [::vector-with-sum-8]}
235+
[_ _]
236+
"This should be a vector of numbers.")
237+
```
238+
239+
has even higher priority and changes the result to this.
240+
241+
```clojure
242+
(phrase-first {} ::vector-with-sum-8 [1 2 "3" 4])
243+
;;=> "This should be a vector of numbers."
244+
```
245+
150246
### More Complex Example
151247

152248
If you like to validate more than one thing, for example correct length and various regexes, I suggest that you build a spec using `s/and` as opposed to building a big, complex predicate which would be difficult to match.

0 commit comments

Comments
 (0)