Fork me on GitHub

Anyone know how to define a custom spec transformations using the built in reitit coercion middleware?


For example, if I want to define how to encode and decode a custom type



(s/def ::created-at
     {:spec (s/spec :clj-time.spec/date-time)
      :swagger/type "string"
      :swagger/format "date-time"
      :decode/string (fn [_ y]
                       (clj-time.coerce/to-string y))
      :encode/string clj-time.coerce/from-string}))


^ this doesn't work as expected


@johnnyillinois encode should also be 2-arity fn:

(require '[clojure.spec.alpha :as s])
(require '[spec-tools.core :as st])

(def spec
    {:spec (s/and int? #(> % 10))
     :swagger/type "integer"
     :decode/string (fn [_ y]
                      (Long/parseLong y))
     :encode/string (fn [_ y]
                      (str y))}))

(as-> "11" $
      (doto $ prn)
      (st/decode spec $ st/string-transformer)
      (doto $ prn)
      (st/encode spec $ st/string-transformer)
      (doto $ prn))
; "11"
; 11
; => "11"


I agree! After looking at the stacktrace, I don't think the encoder is called. But I will try now


That works!

(def my-spec
     {:spec (s/and int? #(> % 10))
      :swagger/type "integer"
      :decode/string (fn [_ y]
                       (println y)
      :encode/string (fn [_ y]
                       (str y))}))

  (def test-router
     ["/:created-at" {:name ::user-view
                                  :coercion reitit.coercion.spec/coercion
                                  :parameters {:path {:created-at my-spec}}}]
     {:compile coercion/compile-request-coercers}))

  (def x (r/match-by-path test-router "/11"))
  (def q (coercion/coerce! x))
  (do q) => {:path {:created-at 11}}


Thank you. I see you are replying to the issue. I'll put the documentation on github

👍 4

Btw, heading for 5 week vacation starting tomorrow, and in July mostly out of internet.

👍 8
🙌 4
Toni Vanhala06:06:34

Highly recommend the five-week Finnish summer vacation for everyone. After that you can join us at #clojutre to meet&greet @ikitommi. 😄

🌴 4

There seems to be a bunch of frontend PR’s almost finished, would be nice to cut a release of those.

Toni Vanhala06:06:34

Highly recommend the five-week Finnish summer vacation for everyone. After that you can join us at #clojutre to meet&greet @ikitommi. 😄

🌴 4

in this example: it saves the state of logged user to state atom, how can i replace this state atom to save it to re-frame db, and how can query the re-frame db, using subscriber ?


so i should create subs to check the value of user in re-frame db, and add @(rf/subscribe [::user]) rather than state ?, subscriber should be added to re-renderable components?


Yes, it’s very straightforward, just change the :on-change handlers to use #(rf/dispatch [:user-form/edit-password %]) (for example), and then use a subscription to get the value instead of getting it from @form.


also i have another question, if i have multi role users like admin, normal user, how can i authenticate both using controller?, what is the best way to extend the code in page i mentioned above?


We have a controller that looks like this:

(def require-auth-controller
  {:start (fn [m]
            ;; If not logged in, go to :login, then return to original destination
            (rf/dispatch [:nav/ensure-login (get-in m [:data :name])]))})
The :nav/ensure-login handler checks whether we have a value for :current-user (which is only filled in for logged-in users), and dispatches a :nav/login-required event if not.
  (fn-traced [{:keys [db]} [_ page]]
    (let [user (:current-user db)]
      (if (empty? user)
        {:dispatch [:nav/login-required page]}))))
Note that we’re passing the original page through to the “login required” handler so we can return to the original page after login. The :nav/login-required handler stores the original page in the app-db, and then redirects to the login page. So if the user tries to go to a page that requires a login, they will immediately be redirected to the login screen if they’re not already logged in.


After logging in, the “login success” handler checks the app-db for a :return-to-page value, and if it’s not null, it redirects the user back to the original page.


also how can i navigate the page without using rfe/href ?


The rfe/href should work fine, but you can just as easily dispatch something like a :nav/go-to-page event. Ours looks like this:

  (fn-traced [_ [_ page]]
    (rfe/push-state page)))
and you call it like this (rf/dispatch [:nav/go-to-page :dashboard]).

☝️ 4

guys how do you use re-frame app-db with reitit state atom ?