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
Malli transforms makes this easy to do
It has raised another question. @ikitommi when you have a chance, can you comment on the 2 questions?
@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)))
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”
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]
not in the public repo, in my private app
If you have and example of multi-schema that doesn’t work, please share, I could take a look
thanks. will do.
and I’ll try m/explainer as well 🙂
transformers are computed into interceptor chains, where the order matters.
I think that’s the right direction to solve it: ordering
but I’ll start with the simpler (public) example
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.
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}}
yep: tried that too. failed. I’ll dig deeper
I’ll get back to you. making this work makes the fork/malli integration nice and idiomatic on both sides
so worth the effort from me
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
maybe that could be polished into having ,
& or
s by default?
ok. I’ll try that too. and I’ll send a PR for the english grammar if required
end of the day here (Sydney) so probably not till tomorrow
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)} ...
this way, the :multi
selects the branch correctly before anything else, and the key-transformer
& string-transformer
both work correctly.
ok. here’s a simple test case from the demo repo….
(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?