9

Say I have the following specs:

(s/def :person/age number?)
(s/def :person/name string?)

(s/def ::person (s/keys :req [:person/name :person/age]))

Then I fetch an entity from Datomic:

(def person-entity (d/entity (d/db conn) [:person/name "Mr entity"]))

If I try to check conformance with the spec it fails because entities are not maps:

(s/explain ::person person-entity)

val: #:db{:id 17592186069950} fails spec: :some-ns/person predicate: map?

My app has functions that take entities as arguments and would like to avoid having to reify entities to maps everywhere just to get spec instrumentation to work in development.

How should I go about validating entities through spec?

Odinodin
  • 2,147
  • 3
  • 25
  • 43
  • 1
    Good question. After you find a solution to this problem, won't you also run into an issue with namespaces? The entity map will be something like: `{:person/name "Mr. Entity"}`, which does _not_ validate against `(s/keys :req [::name ::age])` unless those definitions happen to be in `(ns person)`. But that forces you to define a bunch of top level package namespaces, which doesn't seem reasonable. – Marc Oct 11 '16 at 12:44
  • Thanks @Marc, I've updated the example. – Odinodin Oct 12 '16 at 06:17

1 Answers1

3

Although it is true that your namespaces are a bit off (you should be using :person/name instead of ::name), there is also a restriction in spec that could be lifted. Currently s/keys requires that all input collections conform to the clojure.core/keys predicate. Datomic entities are not maps, and so do not pass that check (and hence the error about the map? predicate).

I've filed a bug report here: http://dev.clojure.org/jira/browse/CLJ-2041 Feel free to upvote/follow the ticket if you wish.

Timothy Baldridge
  • 10,455
  • 1
  • 44
  • 80