Tutorial

Exploring Directives in Prisma

Updated on April 4, 2022
Default avatar

By Joshua Hall

Exploring Directives in Prisma

This tutorial is out of date and no longer maintained.

Besides the many hours of grunt work that Prisma saves by generating our CRUD operations for us, it also gives us access to a few other features that’ll save us even more time and give us more sophisticated control over our data structure. In this article, we’re going to be exploring some of the most common directives you’ll be using in your schemas.

Prerequisites

Were going to be doing things that will help enhance our schemas, so you can refresh on the basics here.

You’re also going to need a basic Prisma container setup with a database of your choice. You can either check out this article or setting up Prisma with Docker, or you can just copy this repo and deploy it onto a new container.

Unique Directive

Imagine we have an app and we want to add a new user while securing our app against users with the same email. Instead of having to manually send a query and check if a match already exists before saving something to the database, Prisma gives us a handy @unique directive that’ll handle it for us. ID’s have their own special equivalent, just called @id, which does basically the same thing.

type User {
  id: ID! @id
  name: String!
  email: String! @unique 
  age: Int!
}

With that we can have a condition to tell the user it wasn’t available when a mutation fails.

Default Directive

Many times we obviously don’t want to make the user fill out everything their account may need, like whether they’re a basic user or an admin. It would be very useful to be able to add default values for those types of data.

The simplest way of handling that would be to just use the @default directive to add a placeholder value.

type User {
  id: ID! @id
  name: String!
  email: String! @unique
  type: UserType! @default(value: USER)
}

enum UserType {
  USER 
  ADMIN
}

Rename Directive

Our data structures aren’t going to be built once and used forever, we eventually going to need to change some things around. While Prisma is pretty good about adding and removing new properties and types, it can have some problems when you want to rename a type that already has saved data reliant on it.

@rename is a temporary directive, meaning that we just use it once, redeploy our schema, then remove it from datamodel.graphql.

type User {
  id: ID! @id
  name: String!
  email: String!
  posts: [Content!]
}

type Content {
  id: ID! @id 
  title: String! @unique 
  body: String! 
  author: User!
}

Content is a pretty vague name, let’s use @rename to change it to something a bit more explicit.

type User {
  id: ID! @id
  name: String!
  email: String!
  posts: [Content!]
}

type Post @rename(oldName: "Content") {
  id: ID! @id 
  title: String! @unique 
  body: String! 
  author: User!
}

Move into your prisma folder and redeploy your schema.

$ prisma deploy

Now you can safely remove @rename without messing up your data.

Relation Directive

The most useful and common thing you’ll be doing with directives is setting up relationships between your data types.

If we removed a product from our store, we would obviously want to remove every review for it from the database. If we were to delete the owner of that product we’d remove their products and the subsequent reviews. The problem is there needs to be a specific way of organizing this hierarchy, because we wouldn’t want to remove the user when their product or a review is removed.

The @relation directive solves this problem pretty elegantly, we just need to pass a name that will link the two types together and tell it what we want done onDelete, Either to stop or continue the deletions down the chain. CASCADE will delete the type on the other side of the chain, while SET_NULL will leave it.

type User {
  id: ID! @id
  name: String!
  selling: [Product!] @relation(name: "UserToProduct", onDelete: CASCADE)
}

type Product {
  id: ID! @id 
  name: String!
  seller: User! @relation(name: "UserToProduct", onDelete: SET_NULL)
  reviews: [Review!] @relation(name: "ProductToReview", onDelete: CASCADE)
}

type Review {
  id: ID! @id 
  author: User! 
  review: String!
  product: Product! @relation(name: "ProductToReview", onDelete: SET_NULL)
}

Closing Thoughts

There are a few more options that are worth checking out over in the official docs.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Joshua Hall

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel