This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-07-31
Channels
- # beginners (9)
- # boot (38)
- # cider (7)
- # cljs-dev (181)
- # cljsrn (49)
- # clojure (136)
- # clojure-italy (44)
- # clojure-losangeles (1)
- # clojure-news (1)
- # clojure-russia (3)
- # clojure-sanfrancisco (1)
- # clojure-serbia (2)
- # clojure-spec (28)
- # clojure-uk (41)
- # clojure-ukraine (1)
- # clojurescript (103)
- # core-async (6)
- # core-logic (46)
- # cursive (5)
- # data-science (8)
- # datascript (6)
- # datomic (5)
- # emacs (35)
- # events (3)
- # jobs (2)
- # jobs-rus (2)
- # juxt (6)
- # lumo (7)
- # off-topic (101)
- # om (6)
- # onyx (6)
- # parinfer (38)
- # pedestal (5)
- # perun (1)
- # planck (4)
- # protorepl (4)
- # re-frame (62)
- # reagent (20)
- # remote-jobs (1)
- # ring-swagger (1)
- # spacemacs (16)
- # unrepl (43)
- # vim (13)
@seancorfield Aha! Thank you!
I'd like to check some javascript data based on a regular spec which uses s/keys and s/coll-of.
I know it's not in scope for clojure-spec but perhaps someone has written something which does this?
(s/assert-obj ::typical-spec #js {:a [1 2 3]})
@camdez if you are dealing with deeply nested legacy models and only want to validate those in the api layer - after which you only transform them to conform your own application specs - you could check out data-specs (in spec-tools lib). Builds on top of clojure.spec. It’s *not* a good/best practise, but food for thought anyway. Something like:
(require '[clojure.spec.alpha :as s])
(require '[spec-tools.data-spec :as ds])
(s/def ::business
(ds/spec
::business
{:id integer?
:name string?
:phone_number {:id integer?
:phone_number string?}}))
(s/valid?
::business
{:id 214566,
:name "Fake Co",
:phone_number {:id 141683, :phone_number "555 123 4567"}})
; true
a sample bare-bones http api with it: https://github.com/ikitommi/business, added a :tags
(a set of keywords) to demonstrate the automatic coercion (string->keyword & vector->set here)
Thanks! I’ve used Plumatic (née Prismatic) Schema quite a bit, so this schema-resembles-data approach is quite familiar. But I’ve been using keyword prefixes divorced from the extant namespaces and it’s working pretty well for me, if a tad verbose.
@olivergeorge simplest thing that comes to mind is to just js->clj
and run spec over the result
@bfabry @olivergeorge js->clj
and clj->js
are not symmetric, beware
hello everyone, im trying to spec a map where all keys are optional but you should have at least one of them, is this achievable?
you can use any predicate function as a spec 🙂 though not-empty isn't technically a predicate function but it's good enough
well, clojure treats nil and false as false and everything else as true. so yeah spec does too
cljs.user=> (s/valid? (s/and (s/keys :opt [::foo]) not-empty) {::foo nil})
true
cljs.user=> (s/valid? (s/and (s/keys :opt [::foo]) not-empty) {})
false
cljs.user=> (s/explain (s/and (s/keys :opt [::foo]) not-empty) {})
val: {} fails predicate: not-empty
:cljs.spec.alpha/spec #object[cljs.spec.alpha.t_cljs$spec$alpha16935]
:cljs.spec.alpha/value {}
nil
It doesn’t appear to be possible to use an s/cat
spec for an argument. Does this instrument failure make sense?
user=> (require '[clojure.spec.alpha :as s] '[clojure.spec.test.alpha :as st])
nil
user=> (s/def ::ingredient (s/cat :quantity number? :unit keyword?))
:user/ingredient
user=> (s/valid? ::ingredient [0 :teaspoon])
true
user=> (defn none? [ingredient] (zero? (first ingredient)))
#'user/none?
user=> (s/fdef none? :args (s/cat :ingredient ::ingredient))
user/none?
user=> (st/instrument)
[user/none?]
user=> (none? [0 :teaspoon])
ExceptionInfo Call to #'user/none? did not conform to spec:
In: [0] val: [0 :teaspoon] fails spec: :user/ingredient at: [:args :ingredient :quantity] predicate: number?
:clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__1200 0x379e0a93 "clojure.spec.alpha$regex_spec_impl$reify__1200@379e0a93"]
:clojure.spec.alpha/value ([0 :teaspoon])
:clojure.spec.alpha/args ([0 :teaspoon])
:clojure.spec.alpha/failure :instrument
:clojure.spec.test.alpha/caller {:file "form-init192069056035209642.clj", :line 1, :var-scope user/eval1427}
clojure.core/ex-info (core.clj:4725)
You should wrap ::ingredient
with s/spec
, like (s/fdef none? :args (s/cat :ingredient (s/spec ::ingredient)))
@bfabry, i think i found a problem
(s/def ::my-spec (s/and not-empty (s/keys :opt-un [::a ::b])))
(s/valid? ::my-spec {} => false
(s/valid? ::my-spec {:A 1 :c 1}) => true
@plins well, that's not so much a problem you just didn't fully explain your requirements to me 😛