#clojure #datomic #clojure.spec
#clojure #datomic #clojure.spec
Вопрос:
Допустим, у меня есть следующие спецификации:
(s/def :person/age number?)
(s/def :person/name string?)
(s/def ::person (s/keys :req [:person/name :person/age]))
Затем я извлекаю объект из Datomic:
(def person-entity (d/entity (d/db conn) [:person/name "Mr entity"]))
Если я попытаюсь проверить соответствие спецификации, это не удастся, потому что объекты не являются картами:
(s/explain ::person person-entity)
val: #:db{:id 17592186069950} fails spec: :some-ns/person predicate: map?
В моем приложении есть функции, которые принимают сущности в качестве аргументов, и я хотел бы избежать необходимости везде привязывать объекты к картам, чтобы заставить спецификацию работать в разработке.
Как мне выполнить проверку объектов через спецификацию?
Комментарии:
1. Хороший вопрос. После того, как вы найдете решение этой проблемы, не столкнетесь ли вы также с проблемой с пространствами имен? Сопоставление объектов будет выглядеть примерно так:
{:person/name "Mr. Entity"}
, который не проверяется(s/keys :req [::name ::age])
, если только эти определения не находятся внутри(ns person)
. Но это заставляет вас определять кучу пространств имен пакетов верхнего уровня, что не кажется разумным.2. Спасибо @Marc, я обновил пример.
Ответ №1:
Хотя верно, что ваши пространства имен немного ограничены (вы должны использовать :person /name вместо ::name ), в спецификации также есть ограничение, которое может быть снято. В настоящее время s / keys требует, чтобы все входные коллекции соответствовали clojure.core/keys
предикату. Объекты Datomic не являются картами и поэтому не проходят эту проверку (и, следовательно, ошибка в отношении map?
предиката).
Я отправил отчет об ошибке здесь: http://dev.clojure.org/jira/browse/CLJ-2041 Не стесняйтесь голосовать / следить за билетом, если хотите.