Skip to content

Commit

Permalink
Merge pull request #278 from metosin/default-value-transformer-options
Browse files Browse the repository at this point in the history
Options for default-value-transformer
  • Loading branch information
ikitommi authored Oct 13, 2020
2 parents 228a3a3 + 4397d26 commit d3f9605
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 27 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ Malli is in [alpha](README.md#alpha).
* New options
* `:malli.core/disable-sci` for explicitly disabling `sci`, fixes [#276](https://github.com/metosin/malli/issues/276)
* `:malli.core/sci-options` for configuring `sci`
* `malli.transform/default-value-transformer` accepts options `:key` and `:defaults`:

```clj
(m/decode
[:map
[:user [:map
[:name :string]
[:description {:ui/default "-"} :string]]]]
nil
(mt/default-value-transformer
{:key :ui/default
:defaults {:map (constantly {})
:string (constantly "")}}))
; => {:user {:name "", :description "-"}}
```

## 0.1.0 (2020-10-08)

Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,22 @@ Applying default values:
; => 42
```

With custom key and type defaults:

```clj
(m/decode
[:map
[:user [:map
[:name :string]
[:description {:ui/default "-"} :string]]]]
nil
(mt/default-value-transformer
{:key :ui/default
:defaults {:map (constantly {})
:string (constantly "")}}))
; => {:user {:name "", :description "-"}}
```

Single sweep of defaults & string encoding:

```clj
Expand Down
56 changes: 30 additions & 26 deletions src/malli/transform.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -367,32 +367,36 @@
(= :default types) {:default-decoder (transform decode :enter)
:default-encoder (transform encode :leave)}))))

(defn default-value-transformer []
(let [get-default (fn [schema] (some-> schema m/properties :default))
set-default {:compile (fn [schema _]
(if-some [default (get-default schema)]
(fn [x] (if (nil? x) default x))))}
add-defaults {:compile (fn [schema _]
(let [defaults (->> (m/children schema)
(keep (fn [[k {:keys [default]} v]]
(if-some [default (if (some? default) default (get-default v))]
[k default])))
(into {}))]
(if (seq defaults)
(fn [x]
(if (map? x)
(reduce-kv
(fn [acc k v]
(if-not (contains? x k)
(assoc acc k v)
acc))
x defaults)
x)))))}]
(transformer
{:default-decoder set-default
:default-encoder set-default}
{:decoders {:map add-defaults}
:encoders {:map add-defaults}})))
(defn default-value-transformer
([]
(default-value-transformer nil))
([{:keys [key defaults] :or {key :default}}]
(let [get-default (fn [schema] (let [default (some-> schema m/properties key)]
(if (some? default) default (some->> schema m/type (get defaults) (#(% schema))))))
set-default {:compile (fn [schema _]
(if-some [default (get-default schema)]
(fn [x] (if (nil? x) default x))))}
add-defaults {:compile (fn [schema _]
(let [defaults (->> (m/children schema)
(keep (fn [[k {default key} v]]
(if-some [default (if (some? default) default (get-default v))]
[k default])))
(into {}))]
(if (seq defaults)
(fn [x]
(if (map? x)
(reduce-kv
(fn [acc k v]
(if-not (contains? x k)
(assoc acc k v)
acc))
x defaults)
x)))))}]
(transformer
{:default-decoder set-default
:default-encoder set-default}
{:decoders {:map add-defaults}
:encoders {:map add-defaults}}))))

(defn collection-transformer []
(let [coders {:vector -sequential-or-set->vector
Expand Down
13 changes: 12 additions & 1 deletion test/malli/transform_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,18 @@
(testing "default false"
(is (= {:user/verified false} (m/decode [:map [:user/verified [:and {:default false} boolean?]]] {} mt/default-value-transformer)))
(is (= {:user/verified false} (m/decode [:map [:user/verified {:default false} boolean?]] {} mt/default-value-transformer)))
(is (= false (m/decode [:and {:default false} boolean?] nil mt/default-value-transformer)))))
(is (= false (m/decode [:and {:default false} boolean?] nil mt/default-value-transformer))))

(testing "with custom options"
(is (= false (m/decode [:and {:? false} boolean?] nil (mt/default-value-transformer {:key :?}))))
(is (= {:user {:first-name "", :last-name ""}}
(m/decode [:map
[:user [:map
[:first-name :string]
[:last-name :string]]]]
nil
(mt/default-value-transformer {:defaults {:map (constantly {})
:string (constantly "")}}))))))

(deftest type-properties-based-transformations
(is (= 12 (m/decode malli.core-test/Over6 "12" mt/string-transformer))))
Expand Down

0 comments on commit d3f9605

Please sign in to comment.