diff --git a/docs/reusable-schemas.md b/docs/reusable-schemas.md index 3403413e5..9b5413dbb 100644 --- a/docs/reusable-schemas.md +++ b/docs/reusable-schemas.md @@ -194,8 +194,7 @@ You should pick the way what works best for your project. # Future Work 1. Could we also decomplect the Maps, Keys and Values with the Var Style? -2. Clear separation of [Entities and Values](https://martinfowler.com/bliki/EvansClassification.html) -3. Utilities for transforming between inlined and referenced models (why? why not!) +2. Utilities for transforming between inlined and referenced models (why? why not!) ```clojure (-flatten-refs diff --git a/src/malli/core.cljc b/src/malli/core.cljc index 80dd23bd8..30d85ed6a 100644 --- a/src/malli/core.cljc +++ b/src/malli/core.cljc @@ -345,6 +345,9 @@ (if (-equals properties (-properties schema)) schema (-into-schema (-parent schema) properties (or (and (-entry-schema? schema) (-entry-parser schema)) (-children schema)) (-options schema)))) +(defn -update-properties [schema f & args] + (-set-properties schema (not-empty (apply f (-properties schema) args)))) + (defn -update-options [schema f] (-into-schema (-parent schema) (-properties schema) (-children schema) (f (-options schema)))) @@ -2310,12 +2313,13 @@ "Derefs all schemas at all levels. Does not walk over `:ref`s." ([?schema] (deref-recursive ?schema nil)) - ([?schema options] - (let [schema (schema ?schema options)] + ([?schema {::keys [ref-key] :as options}] + (let [schema (schema ?schema options) + maybe-set-ref (fn [s r] (if (and ref-key r) (-update-properties s assoc ref-key r) s))] (-> (walk schema (fn [schema _ children _] (cond (= :ref (type schema)) schema - (-ref-schema? schema) (first children) + (-ref-schema? schema) (-> children (first) (maybe-set-ref (-ref schema))) :else (-set-children schema children))) {::walk-schema-refs true}) (deref-all))))) diff --git a/src/malli/util.cljc b/src/malli/util.cljc index 284d3df99..b743d15b3 100644 --- a/src/malli/util.cljc +++ b/src/malli/util.cljc @@ -109,7 +109,7 @@ "Returns a Schema instance with updated properties." [?schema f & args] (let [schema (m/schema ?schema)] - (m/-set-properties schema (not-empty (apply f (m/-properties schema) args))))) + (apply m/-update-properties schema f args))) (defn closed-schema "Maps are implicitly open by default. They can be explicitly closed or diff --git a/test/malli/core_test.cljc b/test/malli/core_test.cljc index 5c03a0eb4..2a6db5015 100644 --- a/test/malli/core_test.cljc +++ b/test/malli/core_test.cljc @@ -3052,12 +3052,21 @@ [:name :string] [:friends {:optional true} [:set [:ref ::user]]] [:address ::address]]}} - ::user] - expected [:map - [:id :uuid] - [:name :string] - [:friends {:optional true} [:set [:ref ::user]]] - [:address [:map - [:street :string] - [:lonlat {:optional true} [:tuple :double :double]]]]]] - (is (= expected (m/form (m/deref-recursive schema)))))) + ::user]] + (is (= [:map + [:id :uuid] + [:name :string] + [:friends {:optional true} [:set [:ref ::user]]] + [:address [:map + [:street :string] + [:lonlat {:optional true} [:tuple :double :double]]]]] + (m/form (m/deref-recursive schema)) + (m/form (m/deref-recursive schema {::m/ref-key nil})))) + (is (= [:map {:id ::user} + [:id [:uuid {:id ::user-id}]] + [:name :string] + [:friends {:optional true} [:set [:ref ::user]]] + [:address [:map {:id ::address} + [:street :string] + [:lonlat {:optional true} [:tuple :double :double]]]]] + (m/form (m/deref-recursive schema {::m/ref-key :id}))))))