Fork me on GitHub
#malli
<
2020-07-13
>
steveb8n06:07:19

I enhanced the Malli/Fork integration demo to use idiomatic keyword maps in the re-frame app-db and string keyword for Fork forms. @lucio

👍 3
steveb8n06:07:45

Malli transforms makes this easy to do

steveb8n06:07:23

It has raised another question. @ikitommi when you have a chance, can you comment on the 2 questions?

ikitommi08:07:40

@steveb8n sure: 1. m/explainer returns a optimized pure function for explaining, e.g:

(m/explainer [:map [:x int?]])
2. mt/transformer can be used to compose transformers, runs them in single sweep. Also, you could store the computed m/decoder :
(m/decoder
  [:map [:x int?]]
  (mt/transformer (mt/key-transformer {:decode keyword}) (mt/string-transformer)))

steveb8n08:07:23

thanks. for #2 I tried the composition via mt/transformer but couldn’t get it to transform properly. I am adding complexity by using it with a “multi-schema”

ikitommi08:07:24

at best, the m/decoder (or m/encoder) know there is nothing to do and return identity:

(m/decoder
  [:map [:x int?]]
  (mt/transformer
    (mt/json-transformer)
    (mt/json-transformer)
    (mt/json-transformer)
    (mt/json-transformer)))
; => #object[clojure.core$identity]

steveb8n08:07:13

not in the public repo, in my private app

ikitommi08:07:13

If you have and example of multi-schema that doesn’t work, please share, I could take a look

steveb8n08:07:30

thanks. will do.

steveb8n08:07:42

and I’ll try m/explainer as well 🙂

👍 3
ikitommi08:07:09

transformers are computed into interceptor chains, where the order matters.

steveb8n08:07:13

I think that’s the right direction to solve it: ordering

steveb8n08:07:34

but I’ll start with the simpler (public) example

ikitommi08:07:37

also, as the transformers are mounted from root schema towards leafs, the :multi decoding is applied before it’s childs (as we don’t know which child is selected), so you might need to decode the :multi dispatch key manually.

ikitommi08:07:07

there is an example in the README:

(m/decode
  [:multi {:dispatch :type
           :decode/string '#(update % :type keyword)}
   [:sized [:map [:type [:= :sized] [:size int?]]]
   [:human [:map [:type [:= :human]] [:name string?] [:address [:map [:country keyword?]]]]]]
  {:type "human"
   :name "Tiina"
   :age "98"
   :address {:country "finland"
             :street "this is an extra key"}}
  (mt/transformer mt/strip-extra-keys-transformer mt/string-transformer))
;{:type :human
; :name "Tiina"
; :address {:country :finland}}

steveb8n08:07:23

yep: tried that too. failed. I’ll dig deeper

👌 3
steveb8n08:07:11

I’ll get back to you. making this work makes the fork/malli integration nice and idiomatic on both sides

steveb8n08:07:20

so worth the effort from me

ikitommi08:07:25

oh, noticed you have the custom error message for :enum: {:error/message "Must be London or Tampere"}. Enums have something decend nowadays by default: https://github.com/metosin/malli/blob/master/src/malli/error.cljc#L63-L66

ikitommi08:07:51

maybe that could be polished into having , & or s by default?

steveb8n08:07:37

ok. I’ll try that too. and I’ll send a PR for the english grammar if required

steveb8n08:07:59

end of the day here (Sydney) so probably not till tomorrow

ikitommi08:07:45

My guess is that you should have a new named transformer, something like:

(mt/transformer 
  {:name :before}
  (mt/key-transformer {:decode keyword}) 
  (mt/string-transformer))
and in the :multi:
[:multi {:dispatch :type
         :decode/before '#(update % :type keyword)} ...

ikitommi08:07:07

this way, the :multi selects the branch correctly before anything else, and the key-transformer & string-transformer both work correctly.

steveb8n23:07:54

ok. here’s a simple test case from the demo repo….

steveb8n23:07:15

(let [v {"id"               "123"
         "github-followers" "10"}
      schema [:map
              [:id :string]
              [:github-followers pos-int?]]]
  (->> (mt/transformer (mt/key-transformer {:decode keyword})
                       mt/string-transformer)
       (m/decode schema v)
       cljs.pprint/pprint))
why does the string transformer not work?