Fork me on GitHub
#clojure-spec
<
2017-03-10
>
ikitommi08:03:11

@tbaldridge you are doing json schema? here too. I think there are ~4 people doing the same now. Should we do join efforts somehow?

Yehonathan Sharvit11:03:35

Is it a good idea to use spec for validating data before inserting it into a mongodb document?

Yehonathan Sharvit11:03:17

The problem I have is that spec is “open” and we have been told by Rich that it is a bad idea to have “closed” specs

Yehonathan Sharvit11:03:55

But I need to make sure I catch typo errors like fristname instead of firstname

bronsa11:03:37

if your firstname key is required spec will still catch it as a missing required key

Yehonathan Sharvit11:03:06

Yes but in my case it’s an optional key

yonatanel11:03:06

@viebel What's the behavior you're looking for?

Yehonathan Sharvit12:03:31

I’d like s/valid? ::my-spec to fails for {:fristname “Jo” :age 10} but to succeed for {:firstname “Jo” :age 10}

Yehonathan Sharvit12:03:27

(s/def ::my-spec (s/keys :opt-un [::firstname ::age])) will not catch this error

yonatanel12:03:17

Maybe roll your own using clojure.core/keys

Yehonathan Sharvit12:03:37

My question is not technical but philosophical

Yehonathan Sharvit12:03:06

I mean: is it good practice to forbid keys?

Yehonathan Sharvit12:03:33

In a lot of occasions Rich and @alexmiller recalls us that specs should be "open"

yonatanel12:03:02

Forbidding keys will inhibit forward compatibility, mixing keys e.g for metadata etc.

yonatanel12:03:48

In your case, I would at least select-keys and dissoc nils before persisting data.

Alex Miller (Clojure team)12:03:51

You can catch invalid keys without writing the exclusion into the spec

Yehonathan Sharvit12:03:30

(In my case it’s a deeply nested map)

Alex Miller (Clojure team)13:03:06

You can write code, admittedly more challenging with nesting

devth14:03:19

@alexmiller hey heads up, i think there's a typo in the blog post http://blog.cognitect.com/blog/2016/8/24/combining-specs-with-and. (s/conform (s/and int? even? #(> % 1000)) 1111) evals to :clojure.spec/invalid, not 1111

Alex Miller (Clojure team)15:03:52

@devth indeed, although that should have just been an even number

yonatanel16:03:39

@viebel If you write a closed keys predicate for each parent key and combine with s/keys, it will drill down the nested map. (s/and (s/keys ...) your-closed-keys-pred?)

joshkh17:03:43

bit of a newbie question about spec... i'm currently using gen/generator to generate some maps with UUIDs. i'd then like to generate another set of maps that will contain vectors of those UUIDs. i can generate both sets of maps and then assoc the UUIDs from one set to the other but i'm wondering if there's a better workflow for this?

not-raspberry17:03:19

Like {:a #uuid "sth", :b #uuid "sth-else"} and {:sths [#uuid "sth", #uuid "sth-else"]}?

joshkh17:03:20

yes, i think so. my example is a collection of "items" with UUIDs {:type :item :uuid #someuuid} and then another spec for a "package" containing random items {:type :package :contents [#someuuid #someotheruuid]}

not-raspberry17:03:14

i'm no expert but I'd just write a function for that transformation

not-raspberry17:03:47

and have specs for both data structures

joshkh17:03:42

yes, i have specs for both data structures. after generating samples of both i can just reassoc contents from one collection to the other

joshkh18:03:15

i was using this blog post as an example but i'm not sure i understand gen/fmap https://product.gomore.com/end-to-end-integration-tests-with-clojure-spec-d4a48cbf92b5#.kpvs9132v

gfredericks18:03:42

gen/fmap lets you transform the value that a generator generates

gfredericks18:03:54

so e.g., if you have a generator integers g, then (gen/fmap str g) is a generator of stringified integers

Alex Miller (Clojure team)19:03:59

I have been remiss in not mentioning that I will be doing clojure.spec training before the Conj in Portland March 29th - you can register independently from Clojure/west (although why would you want to?) http://2017.clojurewest.org/training/

peeja22:03:54

Is there something like s/multi-spec that doesn't use the extra machinery of a multimethod that would be more appropriate for a situations where the cases are a closed set? I don't need to be able to extend the list of cases easily.

peeja22:03:46

I could use s/or, but that doesn't dispatch by looking at the value being conformed

peeja22:03:51

which maybe is fine?

peeja22:03:46

It seems like dispatching on a tag would be faster in general when it's an option, but since it's a small, close set of variants, maybe it just doesn't matter much

bbloom22:03:49

just use multi-spec

bbloom22:03:10

you can put ^:private on your multimethod if you want

bbloom22:03:15

that’ll keep it closed

yonatanel22:03:36

@peeja It depends on what's bothering you with the multi-spec solution. You can't do much about the style. The set of options is kinda closed and you'll get a "no method" exception on unknown dispatch values. In addition you could define a spec for the dispatch key using a set #{...} to get a nicer explanation for invalid values.

peeja22:03:43

It's not so much that I need to enforce that it's closed (I do have a spec on the key) as much as a multi-method is grammatically pretty heavy and I don't need the advantages it offers. Having written it out, though, the s/or actually works pretty well for me here.

bbloom22:03:27

i do think a syntactic shortcut for the common case of single-keyword dispatch may be warranted

bbloom22:03:29

it’s really not too bad tho