malli

https://github.com/metosin/malli :malli:
steveb8n 2020-07-13T06:23:19.130900Z

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

đź‘Ť 1
steveb8n 2020-07-13T06:23:22.131100Z

https://stevebuik.github.io/fork-malli-ideas/#!/basics

steveb8n 2020-07-13T06:23:45.131600Z

Malli transforms makes this easy to do

steveb8n 2020-07-13T06:24:23.132300Z

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

ikitommi 2020-07-13T08:17:40.135300Z

@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)))

steveb8n 2020-07-13T08:19:23.136900Z

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”

ikitommi 2020-07-13T08:19:24.137Z

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]

steveb8n 2020-07-13T08:20:13.137900Z

not in the public repo, in my private app

ikitommi 2020-07-13T08:20:13.138Z

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

steveb8n 2020-07-13T08:20:30.138400Z

thanks. will do.

steveb8n 2020-07-13T08:20:42.138700Z

and I’ll try m/explainer as well 🙂

đź‘Ť 1
ikitommi 2020-07-13T08:22:09.139400Z

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

steveb8n 2020-07-13T08:23:13.140900Z

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

steveb8n 2020-07-13T08:23:34.141700Z

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

ikitommi 2020-07-13T08:23:37.141900Z

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.

ikitommi 2020-07-13T08:24:07.142400Z

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}}

steveb8n 2020-07-13T08:24:23.142700Z

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

đź‘Ś 1
steveb8n 2020-07-13T08:25:11.143500Z

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

steveb8n 2020-07-13T08:25:20.143700Z

so worth the effort from me

ikitommi 2020-07-13T08:27:25.144500Z

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

ikitommi 2020-07-13T08:27:51.145200Z

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

steveb8n 2020-07-13T08:28:37.145900Z

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

steveb8n 2020-07-13T08:28:59.146300Z

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

ikitommi 2020-07-13T08:51:45.148700Z

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)} ...

ikitommi 2020-07-13T08:53:07.149900Z

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

steveb8n 2020-07-13T23:18:54.150400Z

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

steveb8n 2020-07-13T23:19:15.150800Z

(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?