This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-05-15
Channels
- # aws (4)
- # beginners (98)
- # boot (23)
- # cider (63)
- # cljsrn (3)
- # clojure (259)
- # clojure-boston (1)
- # clojure-dev (2)
- # clojure-italy (6)
- # clojure-nl (17)
- # clojure-russia (1)
- # clojure-serbia (1)
- # clojure-spec (36)
- # clojure-uk (74)
- # clojurescript (11)
- # cursive (2)
- # datascript (12)
- # datomic (36)
- # defnpodcast (1)
- # devops (1)
- # docs (1)
- # emacs (15)
- # euroclojure (3)
- # fulcro (13)
- # graphql (1)
- # juxt (2)
- # lumo (27)
- # off-topic (46)
- # onyx (23)
- # pedestal (6)
- # planck (2)
- # portkey (27)
- # re-frame (18)
- # reagent (12)
- # remote-jobs (2)
- # ring-swagger (11)
- # rum (4)
- # shadow-cljs (104)
- # spacemacs (4)
- # sql (3)
- # tools-deps (5)
- # vim (45)
I have this compojure-api definition:
(context "/api" []
:coercion :spec
,,,
(POST "/api/check" []
:body-params [user :- ::specs/user
k :- ::specs/k
address :- (s/nilable string?)]
(do-sth user k address version)))
Now I'd like to add a new optional attribute version
(and also fixing existing address
to be truly optional).
What's the easiest way to do it?
(context "/api" []
:coercion :spec
,,,
(POST "/api/check" []
:body-params [user :- ::specs/user
k :- ::specs/k
;; s/nilable isn't enough - 400 bad request is returned if address and version are not present in request params
address :- (s/nilable string?)
version :- (s/nilable string?)]
(do-sth user k address version)))
So far I've found only this solution (which seems to work):
(context "/api" []
,,,
(context "/check" []
(resource
{:coercion :spec
:post {:parameters {:body-params (s/keys :req-un [::specs/user ::specs/k]
:opt-un [::address ::version])}
:handler (fn [{{:keys [user k address version]} :body-params}]
(do-sth user k address version))}})))
@jumar all the -params
use the Plumatic fn
syntax (https://github.com/plumatic/plumbing#bring-on-defnk). With it, the optional is maked with curly braces. This should work:
(def app
(context "/api" []
:coercion :spec
(POST "/check" []
:body-params [{address :- (s/nilable string?) nil}
{version :- (s/nilable string?) nil}]
(ok [address version]))))
(app {:request-method :post, :uri "/api/check", :body-params {}})
; {:status 200, :headers {}, :body [nil nil]}
(app {:request-method :post, :uri "/api/check", :body-params {:address "Hämeenkatu"}})
; {:status 200, :headers {}, :body ["Hämeenkatu" nil]}
@plins Threads should be managed somehow. I would recommend using some lifecycle management solution like Integrant, Mount or Component to start (and stop) those. There is a example of Mount in https://github.com/yogthos/memory-hole
Hey guys sorry for the ignorant question but may I ask why is spec tools build around a separate model instead of using Clojure spec directly? I see this project https://github.com/wilkerlucio/spec-coerce and wonder if there is something that I'm not understanding since I thought that it was not possible to do it based on the current Clojure directly implementation.
@carocad good question! spec-tools actually builds on top of clojure.spec. if the patch in CLJ-2116 would have been accepted, spec-tools would work 100% with normal specs too and st/spec
wrapping could be made optional. There is even an issue about spec meta-data, so we could remove the wrapping completely. For now, there are two ways to do this: 1) lean on s/conform*
which is implemented for all specs (e.g. works with all regexps too) and wrap the specs to enable overriding it at runtime, e.g. "spec-tools way" or b) copy the spec walking code (the s/conform*
impls) into the coercion library. I think spec-coerce
has done this, for most common specs, but not all like regexps. Also, parsing spec forms at each invocation is slow.