|
(ns validate |
|
(:require |
|
[com.rpl.specter :as sp])) |
|
|
|
(declare ^:dynamic *errors*) |
|
|
|
(deftype ScalarWrapper [value]) |
|
|
|
(defn value [x] |
|
(if (instance? ScalarWrapper x) |
|
(.-value x) |
|
x)) |
|
|
|
(defn errors [x] |
|
(if (.containsKey *errors* x) |
|
(.get *errors* x) |
|
(list))) |
|
|
|
(defn add-error [x error] |
|
(let [obj (if (or (instance? java.util.Collection x) |
|
(instance? java.util.Map x) |
|
(instance? ScalarWrapper x)) |
|
x |
|
(ScalarWrapper. x)) |
|
obj-errors (errors obj) |
|
obj-errors (conj obj-errors error)] |
|
(.put *errors* obj obj-errors) |
|
obj)) |
|
|
|
(defn check [path predicate] |
|
(-> (if (vector? path) path [path]) |
|
(conj (sp/pred #(-> % value predicate not))) |
|
(conj (sp/terminal #(add-error % :error))))) ;; что-то осмысленное вместо :error |
|
|
|
|
|
(let [data {:publication/id 1 |
|
:publication/translations {:de {:publication.translation/title nil |
|
:publication.translation/published-at nil |
|
:article.translation/content "foo"} |
|
:ru {:publication.translation/title "article ru" |
|
:pbulication.translation/published-at nil |
|
:article.translation/content "foo ru"}} |
|
:article/image-url "http://"} |
|
path (sp/multi-path (check [:publication/translations] |
|
#(= 3 (count %))) |
|
(check [:publication/translations |
|
sp/MAP-VALS |
|
:publication.translation/title] |
|
string?))] |
|
(binding [*errors* (java.util.IdentityHashMap.)] |
|
[(sp/multi-transform path data) |
|
*errors*])) |
|
|
|
;; результат: |
|
(comment |
|
[ |
|
;; data, невалидные скалярные значения обернуты в ScalarWrapper |
|
;; :de :title |
|
{:publication/id 1, |
|
:publication/translations {:de {:publication.translation/title #object[validate.ScalarWrapper 0x2fc7ae79 "validate.ScalarWrapper@2fc7ae79"], |
|
:publication.translation/published-at nil, |
|
:article.translation/content "foo"}, |
|
:ru {:publication.translation/title "article ru", |
|
:pbulication.translation/published-at nil, |
|
:article.translation/content "foo ru"}}, |
|
:article/image-url "http://"} |
|
|
|
;; мапа с ошибками |
|
;; ключ - ссылка на объект |
|
;; значение - список ошибок |
|
{ |
|
{:de {:publication.translation/title nil, :publication.translation/published-at nil, :article.translation/content "foo"}, :ru {:publication.translation/title "article ru", :pbulication.translation/published-at nil, :article.translation/content "foo ru"}} |
|
(:error), |
|
|
|
#object[validate.ScalarWrapper 0x2fc7ae79 "validate.ScalarWrapper@2fc7ae79"] |
|
(:error) |
|
|
|
}]) |
|
|