Fork me on GitHub
#malli
<
2020-06-30
>
borkdude10:06:31

I made a PR to malli which makes sci optional. The tests are failing, but this is only because the order in which namespaces are loaded is random. sci.core needs to be loaded first. But since sci.core is now optional, the tests have to be refactored accordingly anyway. Just putting this here in case someone has ideas about it.

borkdude10:06:40

Locally the tests pass, FWIW.

borkdude10:06:36

I might put that dynaload code into a library so it can be used in more projects.

ikitommi12:06:12

will check that out, thanks!

ikitommi12:06:20

a separat one-purpose lib would be good

ikitommi12:06:36

merged recursion PR into master.

ikitommi12:06:17

here’s a sample (the generation is blocking the main thread, should port to use web-worker?): https://malli.io/?value=%7B%3Alines%20%5B%7B%3Aburger%20%7B%3Aname%20%22NAUGHTY%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Adescription%20%22Finnish%20100%25%20beef%20patty%2C%20cheddar%2C%20St%20Agur%20blue%20cheese%2C%20bacon%20jam%2C%20rocket%2C%20aioli%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Aorigin%20%7B%3Aname%20%3AFI%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Aprice%2011%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%3Aamount%202%7D%5D%2C%0A%20%3Adelivery%20%7B%3Adelivered%20false%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Aaddress%20%7B%3Astreet%20%22H%C3%A4meenkatu%2010%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Azip%2033100%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Acountry%20%7B%3Aname%20%3AFI%2C%20%3Aneighbors%20%5B%7B%3Aname%20%3APO%7D%5D%7D%7D%7D%7D&amp;schema=%5B%3Aschema%0A%20%7B%3Aregistry%20%7B%3Auser%2Fcountry%20%5B%3Amap%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%3Aclosed%20true%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aname%20%5B%3Aenum%20%3AFI%20%3APO%5D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aneighbors%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%3Aoptional%20true%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Avector%20%5B%3Aref%20%3Auser%2Fcountry%5D%5D%5D%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Auser%2Fburger%20%5B%3Amap%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aname%20string%3F%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Adescription%20%7B%3Aoptional%20true%7D%20string%3F%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aorigin%20%5B%3Amaybe%20%3Auser%2Fcountry%5D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aprice%20pos-int%3F%5D%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Auser%2Forder-line%20%5B%3Amap%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%3Aclosed%20true%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aburger%20%3Auser%2Fburger%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aamount%20int%3F%5D%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3Auser%2Forder%20%5B%3Amap%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%3Aclosed%20true%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Alines%20%5B%3Avector%20%3Auser%2Forder-line%5D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Adelivery%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Amap%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%3Aclosed%20true%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Adelivered%20boolean%3F%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Aaddress%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Amap%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Astreet%20string%3F%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Azip%20int%3F%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Acountry%20%3Auser%2Fcountry%5D%5D%5D%5D%5D%5D%7D%7D%0A%20%3Auser%2Forder%5D

kspriyan3116:06:48

Hi. I have an use case with the data structure and scenario similar to the following example { "name": string, "age": int, "married": boolean, "sex": string "partner": { "husband":{"name": string, "age": int}, "wife":{"name": string, "age": int} } } name in husband is mandatory if the status is married and sex is Male. name in wife is mandatory if status is married and sex is female. both are not needed if married is false. how do i write the malli schema validations for the following scenario. if both the fields are at the same level i could add a function and validation. since one is at a parent and the other field is inside the child, i am unable to find a solution to implement this. any help would be appreciated. thanks in advance

ikitommi17:06:21

hi @kspriyan31. You can add rules to top-level and add error metadata to point into nested fields. Something like:

(def Person
  [:and {:registry {:partner [:map ["name" string?] ["age" int?]]}}
   [:map
    ["name" string?]
    ["age" int?]
    ["married" boolean?]
    ["sex" string?]
    ["partner" {:optional true}
     [:map
      ["husband" {:optional true} :partner]
      ["wife" {:optional true} :partner]]]]
   
   [:fn {:error/message "wife name is mandatory for married men"
         :error/path ["partner" "wife" "name"]}
    (fn [{:strs [sex married partner]}]
      (not (and married (= "male" sex) (not (get-in partner ["wife" "name"])))))]
   
   [:fn {:error/message "husband name is mandatory for married female"
         :error/path ["partner" "wife" "name"]}
    (fn [{:strs [sex married partner]}]
      (not (and married (= "female" sex) (not (get-in partner ["husband" "name"])))))]])

(-> Person
    (m/explain {"name" "Mauno"
                "age" 31
                "married" true
                "sex" "male"
                "partner" {"wife" {"age" 41}}})
    (me/humanize))
;{"partner" {"wife" {"name" ["missing required key" 
;                            "wife name is mandatory for married men"]}}} 

kspriyan3117:06:56

Thank you @ikitommi

ikitommi17:06:25

if you change the sex to [:enum "male" "female" "other"]the sample value generation can generate better values:

({"name" "",
  "age" 1,
  "married" true,
  "sex" "male",
  "partner" {"husband" {"name" "", "age" -1}, "wife" {"name" "", "age" 0}}}
 {"name" "", "age" 2, "married" false, "sex" "male"}
 {"name" "K5", "age" 2, "married" false, "sex" "male", "partner" {"wife" {"name" "", "age" -1}}}
 {"name" "", "age" 3, "married" false, "sex" "male"}
 {"name" "8Mn",
  "age" 3,
  "married" true,
  "sex" "male",
  "partner" {"husband" {"name" "J", "age" -4}, "wife" {"name" "", "age" 3}}}
 {"name" "bsyt4", "age" 1, "married" false, "sex" "female"}
 {"name" "8k5yk", "age" 6, "married" false, "sex" "female", "partner" {"husband" {"name" "4", "age" 13}}}
 {"name" "5ut0D2sm",
  "age" 1,
  "married" true,
  "sex" "female",
  "partner" {"husband" {"name" "", "age" -102}, "wife" {"name" "i4Q5l6xa", "age" 0}}}
 {"name" "", "age" 1, "married" false, "sex" "male"}
 {"name" "l", "age" 3, "married" false, "sex" "male", "partner" {"husband" {"name" "Ixh4drJNb", "age" -37}}})

ikitommi17:06:39

your welcome