Build an AI-Powered Fullstack Next.js App, v3

User & JournalEntry Schemas

Scott Moss

Scott Moss

Superfilter AI
Build an AI-Powered Fullstack Next.js App, v3

Check out a free preview of the full Build an AI-Powered Fullstack Next.js App, v3 course

The "User & JournalEntry Schemas" Lesson is part of the full, Build an AI-Powered Fullstack Next.js App, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Scott completes the User and JournalEntry schemas. A relation between the two schemas is established, and Prisma will ensure the names and types between the joined fields match.

Preview
Close

Transcript from the "User & JournalEntry Schemas" Lesson

[00:00:00]
>> Let's get ready to use our database and our app. And now we can write some data fetching and data mutating functions that take advantage of the database. But the one thing we wanna do is, like I said, we want to sync the clerk user with the user that we're gonna create our database.

[00:00:16]
So let's do that. Before we can do it, we actually have to write a real schema. So let's do that. So back to the schema. Let's just keep working on this user. So we want the user to have a createdAt, and that's just gonna be a DateTime type, and we can give it a default of now.

[00:00:37]
So it's created whenever it got created. You can do an updatedAt, that's very similar, That's a date-time type. I believe there's a updatedAt attribute here, so it'll automatically add that timestamp for us every time this gets updated, so we don't have to manually do it. And then, I mean, we could pretty much put whatever we want.

[00:01:13]
I don't want all the information about a user that clerk has. That would just be hard to just keep that cuz then it's well, what if they go, cuz clerk also allows the user to go change their account. So if they change their account on clerk, then now I gotta write some logic to keep that in sync here too.

[00:01:28]
I just want to keep in sync on the initial signup, I don't really care if they do all the other stuff. In fact, I would just rather just hit clerk's API as a source of truth to get information about my user. I just need to know what user it is.

[00:01:41]
So really, all I need is the id that belongs to that clerk user and add it here. And now I can just ask clerk about this user, whatever I want to know about the user, versus copying all the data over and trying to keep that in sync. It sounds very brittle.

[00:01:53]
It sounds like someone's job. It's like that's the person on the team whose job is to keep the clerk and user in sync. That's a job, so I'm not doing it. We're just gonna add the clerk id. So I'm gonna say clerkId, that's a type string, and it's unique.

[00:02:10]
Only one user can have this click id.
>> Can you make a quick comment about like app decorators we're using, are those leveraging native functions to Prisma?
>> Yeah, so this is Prisma proprietary language I, don't know if they have a name for it. I don't know if it's called Prisma SDL or whatever.

[00:02:34]
But yeah, it's their proprietary language and all of these map to specific database functionalities. In fact, they have a chart that walks through all of it. Here we go. Yeah, so you can see how these map to different things within a database and what they're doing, and that's basically, I think.

[00:02:54]
So the Prisma team used to be a GraphQL server as a service, but really what was cool about that was they built some really cool database functionality to help build that app. And I think they realized that, wait, this database functionality that we built is a really cool product on its own, we should leverage that.

[00:03:14]
So they also have a product that you can use. But if you use something like PlanetScale, you don't need the product that they have, actually, cuz the product they have helps you scale a database on serverless. But if you use PlanetScale, you don't need it. So, PlanetScale is great.

[00:03:31]
Good question though. Cool, okay, so we have that. What else could we put on here? We could put email here if we wanted. Let's do that. That way we can reference this in the UI somewhere, here you are, here's your user email, whatever. That's also unique. And by the way, if you don't put a question mark on the end of this, that means it's required.

[00:03:54]
Everything's required unless it has a question mark on it. So got email, and we can stop with the user for now. And now we're gonna think about all the other models in our app and what we need to make. So the next one is gonna be a journal entry.

[00:04:10]
I'm just gonna copy these three things here because everything's pretty much got to have these three fields, an id, a createdAt, and updatedAt. And then from there, a journal entry has It has content, that's the actual content. It's a string. Because MySQL is a fixed width column database, it's gonna hit a limit on how long that string can be.

[00:04:37]
So to get around that, you can just do db.text or db.Text. There we go. This is basically changing it to full-blown text in the database and not some fixed width char or car. Char, car, I don't know how you pronounce it, it's short for character, which is what it would be by default.

[00:05:02]
If you don't know anything about MySQL, then don't listen to anything I just said. This just means I want my string to be long. [LAUGH] That's what this means. Okay, we have content, what else does an entry have? It has the user that created it, so we need a relationship here.

[00:05:24]
I like to put my relationships up here. To make a relationship, you just need two fields. You need a unique field that associates this entry with the thing you want to relate to. In this case, I'll just call it the userId. You can call it whatever you want.

[00:05:40]
You can call it, ownerId, it doesn't matter. Creator, I'm just gonna call it a userId. Its type is a string because the type of a userId is also a string. If the userId type was int, and you did the auto-increment, then this will also be int for integer.

[00:05:55]
You just got to make sure the type that you put for the relation is the same type that it is on the thing you're relating to. Type string, and then I can say @relation, like this. Then I can say fields, which is an array. And then I can say references.

[00:06:19]
So fields is basically just gonna be the field that you want this relationship to tie into. So in this case, it'll be userId, like so. And then the reference is what is the name of the field on which you're referencing on the other model, in this case, it's id.

[00:06:39]
So I'm referencing id, like that. I'm sorry, hold on. Forget what I just said. That goes on the next one, [LAUGH] not this one. I'm like, wait, this doesn't look right. So actually, we can just change it right now. So instead of saying userId right here, just call this user and give it a type of user like that.

[00:07:06]
And then you can make the userId field, which is just type String. And you'll still get this error, which is expected. We'll talk about why this is the case, but that's how you set up the relationship in this side. So we're saying the userId field on JournalEntry is gonna reference the id field on the user model.

[00:07:31]
So userId here, references id there. And it's freaking out because it's like, yeah, but you got to set up the relationship on the other side too. So let's go do that. We can actually just go back up to user, and you can call this whatever you want. I'll just call it entries.

[00:07:54]
It's a one to many relationship. A journal entry can have one user, but a user can have many entries. So it's gonna be an array of journal entries like that. And then we get one more squiggly here. And this thing is basically saying, hey, relationship mode is Prisma.

[00:08:15]
We're not gonna generate these foreign keys for you, you need to do it yourself. It's a technical issue. Basically, what they're saying is you just need to index that. So we can say, you can go down to the bottom, and you can say index, which is a function that takes an array has two sides in front of it.

[00:08:32]
And you can say index the userId, and that will solve that problem. We will actually probably make this unique because we'll have to query it. But we'll keep it indexed for now, and we'll come back and change it if we need to. Get our journal entry, the last thing we need to make, or at least one more thing, I don't know what else.

[00:08:50]
Yeah. Yep.
>> So, on line 31. You know, the references we know is looking for that value on the type that we've declared on 31. Does it check that about the fields, is it inherently gonna referencing the model that were defining this one.
>> Correct, yeah, so the field is only referencing a field that's on this model, so it's looking for something here with this name.

[00:09:15]
>> Self model.
>> Right, exactly, and yeah, the reference is like, okay, what is the name of the field on the reference that you're talking about, and that's called id. So if this was not called id, if it was like that, you can see it breaks immediately. It's like, there's nothing called that, what are you talking about, so.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now