04: refs
Last updated
Last updated
In all the examples so far, all the todo lists have referred to the same user, :u0
. What if you want to create two todo lists, but you want them to belong to different users? Here's how you could do that:
What's new in this example is the map {:refs {:owner-id :my-own-sweet-user}}
. It resulted in two todo lists, :tl0
and :tl1
, referring to a :user
ent named :my-own-sweet-user
instead of :u0
. :t2
refers to :u0
, as we've seen before. Let's break this down.
In the schema
, :topic
includes this relations definition:
This means, :topic
s refer to a user via the :owner-id
attribute. Remember that queries are essentially telling Specmonstah, generate the minimal ent-db necessary for me to retrieve the ents I've specified, so when you call the add-ents
function and instruct SM to generate a :topic
, SM's default behavior is to satisfy this schema definition by creating a :user
and naming it according to its default naming system.
Internally, the ent db tracks that the :topic
refers to the :user
via the :owner-id
attribute, and when your query includes the option {:refs {:owner-id :my-own-sweet-user}}
, you're saying, I want the user that :owner-id
refers to to be named :my-own-sweet-user
. One reason you might do this would be to write a test ensuring that users can't modify each others' topics.
If you look back at the schema for this section, you'll notice it introduced a new ent type, :topic
, and :post
s reference :topic
s. What if you wanted to create two topics, each with one post and each topic belonging to a different user? Here's how you could do that:
Before reading the explanation of how this works, indulge the educator in me and take a moment to write or say your own explanation. Quizzing yourself like this is an effective way to clarify and retain your understanding. There's all kinds of studies that show it; it's called "the testing effect" and it's one of the best ways to learn.
Let's break this query down term by term:
Under :topic
, [1]
tells Specmonstah to create a :topic
. It's given the default name :t0
. Since you didn't specify any refs, it refers to the default user, :u0
.
The next query term, [1 {:refs {:owner-id :hamburglar}}]
, instructs SM to create a :topic
that refers to a user named, of all things, :hamburglar
. This :topic
is given the default name of :t1
.
Under :post
, [1]
tells Specmonstah to create a :post
with a default name and default refs. Therefore, :p0
refers to :t0
.
The next term, [1 {:refs {:topic-id :t1}}]
, tells SM that the next :todo
should refer to the :topic
named :t1
. We specified the :t1
here because we know that Specmonstah's naming system will produce that name for the second :topic
specified in the query.
The point of all this is that you can rely on Specmonstah's naming system to reliably and concisely establish the properties and relations of the ent db you want to generate. If you don't want to keep track of Specmonstah's implicit names, you can name things explicitly: