Specific question about the "data specs" feature in spec-tools: https://github.com/metosin/spec-tools/blob/master/docs/02_data_specs.md I want to specify a vector of elements where the vector's count = 2. Is this possible to specify using data-specs?
@quest You can certainly specify that with clojure.spec
. No idea about spec-tools
.
Yeah, the :min-count option works fine in normal specs... I'm trying to cast to clojure specs from an EDN business schema I have, proving difficult
I know spec2 has much improved support for runtime specs, but I need the CLJS side unfortunately
Ah, so you can't eval
either...
Sounds like a good compromise for now!
Yeah. I had some success by doing funky things using the spec private "impl" functions, but it completely mangles the error messages when data fails validation
Is it possible to spec a map where either a namespaced key or another unnamespaced key is required? e.g {:my/a 1}
ok, {:my-a 1}
ok, {:my/a 1, :my-a 2}
should also be fine, {:b 2}
invalid.
not directly
you have to spec that with additional predicates. (s/keys)
doesn’t have support for that AFAIK across req/req-un
groups
Spec V1 doesn’t really have a way to say “this map can’t contain :b”. For aliasing :my-a
to :my/a
you could choose a single “canonical” version of your map and use a conformer when you expect there to be variations of it.
(s/def :my/a number?)
(s/def ::m (s/keys :req [:my/a]))
(s/def ::->normalize-keys (s/conformer #(clojure.set/rename-keys % {:my-a :my/a})))
(s/valid? (s/and ::->normalize-keys ::m) {:my-a 1}) ;-> true
(s/valid? (s/and ::->normalize-keys ::m) {:my/a 1}) ;-> true
(s/valid? (s/and ::->normalize-keys ::m) {:my-a "1"}) ;-> false
(s/valid? (s/and ::->normalize-keys ::m) {:my/a "1"}) ;-> false
Depending on what your needs are for generation though this can be troublesome.Yeah, it’s nice, but I wanted (s/explain)
to mention the unnamespaced key if both are missing
@yonatanel this is kind of convoluted but:
(s/def :my/a number?)
(s/def ::my-a :my/a)
(s/def ::m (s/merge (s/nonconforming (s/or :v1 (s/keys :req [:my/a])
:v2 (s/keys :req-un [::my-a])))
(s/keys :opt [:my/a]
:opt-un [::my-a])))
(s/valid? ::m {:my/a 1}) ; true
(s/valid? ::m {:my-a 1}) ; true
(s/valid? ::m {:my/a 1 :my-a 2}) ; true
(s/valid? ::m {:b 2}) ; false
(s/explain-data ::m {:b 2})
(s/exercise ::m)
@colinkahn Thanks. I wasn’t aware of nonconforming
. Gave me some options anyway.
how do I make a (s/coll-off ::foo)
, making sure that the elements are distinct by one given field?
e.g.: if (s/def ::foo (s/keys :req-un [:name]))
, I want that all the names in the generated collection are unique.
nevermind… figure it out… used: (s/and (s/coll-of ,,,, ) #(apply distinct? (mapv :name %)),,,