Skip to content

Commit

Permalink
Merge pull request #644 from metosin/default-fn-polish
Browse files Browse the repository at this point in the history
2-arity default-fn
  • Loading branch information
ikitommi authored Feb 15, 2022
2 parents e298309 + ad0d96d commit ad91b48
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino

Malli is in well matured [alpha](README.md#alpha).

## UNRELEASED

* support for 2-arity `default-fn` option in `mt/default-value-transformer` [#582](https://github.com/metosin/malli/pull/582) & [#644](https://github.com/metosin/malli/pull/644)

## 0.8.3 (2022-02-15)

* FIX: qualified-keyword with namespace doesn't generate the ns [#642](https://github.com/metosin/malli/issues/642)
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,20 @@ With custom key and type defaults:
; => {:user {:name "", :description "-"}}
```

With custom function:

```clj
(m/decode
[:map
[:os [:string {:property "os.name"}]]
[:timezone [:string {:property "user.timezone"}]]]
{}
(mt/default-value-transformer
{:key :property
:default-fn (fn [_ x] (System/getProperty x))}))
; => {:os "Mac OS X", :timezone "Europe/Helsinki"}
```

Single sweep of defaults & string encoding:

```clj
Expand Down
11 changes: 5 additions & 6 deletions src/malli/transform.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -380,23 +380,22 @@
(defn default-value-transformer
([]
(default-value-transformer nil))
([{:keys [key default-fn defaults] :or {key :default, default-fn identity}}]
([{:keys [key default-fn defaults] :or {key :default, default-fn (fn [_ x] x)}}]
(let [get-default (fn [schema]
(if-some [e (some-> schema m/properties (find key))]
(constantly (val e))
(some->> schema m/type (get defaults) (#(constantly (% schema))))))
set-default {:compile (fn [schema _]
(when-some [f (get-default schema)]
(fn [x] (if (nil? x) (default-fn (f)) x))))}
(fn [x] (if (nil? x) (default-fn schema (f)) x))))}
add-defaults {:compile (fn [schema _]
(let [defaults (into {}
(keep (fn [[k {:keys [optional] :as p} v]]
(when-not optional
(let [e (find p key)]
(when-some [f (if e
(constantly (val e))
(get-default v))]
[k (comp default-fn f)])))))
(when-some [f (if e (constantly (val e))
(get-default v))]
[k (fn [] (default-fn schema (f)))])))))
(m/children schema))]
(when (seq defaults)
(fn [x]
Expand Down
15 changes: 9 additions & 6 deletions test/malli/transform_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -832,21 +832,24 @@
[:first {:default 1} int?]
[:second {:default 2} int?]]]
(testing "called on each defaulted value"
(let [seen (atom [])]
(is (= {:first 1, :second 2} (m/encode schema nil (mt/default-value-transformer {:default-fn (fn [x] (swap! seen conj x) x)}))))
(let [seen (atom [])
transformer (mt/default-value-transformer {:default-fn (fn [_ x] (swap! seen conj x) x)})]
(is (= {:first 1, :second 2} (m/encode schema nil transformer)))
(is (= [{} 1 2] @seen))))

(testing "only called on defaulted value"
(let [seen (atom [])]
(is (= {:first -1, :second 2} (m/encode schema {:first -1} (mt/default-value-transformer {:default-fn (fn [x] (swap! seen conj x) x)}))))
(let [seen (atom [])
transformer (mt/default-value-transformer {:default-fn (fn [_ x] (swap! seen conj x) x)})]
(is (= {:first -1, :second 2} (m/encode schema {:first -1} transformer)))
(is (= [2] @seen)))))

(testing "custom default :key"
(let [schema [:map {}
[:first {:default 1, :name 'one} int?]
[:second {:default 2, :name 'two} int?]]]
(let [seen (atom [])]
(is (= {:first 'one, :second 'two} (m/encode schema {} (mt/default-value-transformer {:key :name, :default-fn (fn [x] (swap! seen conj x) x)}))))
(let [seen (atom [])
transformer (mt/default-value-transformer {:key :name, :default-fn (fn [_ x] (swap! seen conj x) x)})]
(is (= {:first 'one, :second 'two} (m/encode schema {} transformer)))
(is (= ['one 'two] @seen)))))))

(deftest type-properties-based-transformations
Expand Down

0 comments on commit ad91b48

Please sign in to comment.