Redwood: Admin view can't create an entity with a reference to another entity

Created on 17 Jun 2020  路  13Comments  路  Source: redwoodjs/redwood

My schema contains two types, Post and User, appearing as below in schema.prisma.

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  author    User?   @relation(fields: [authorId], references: [id])
  authorId  Int?
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

This schema is taken from the prisma quick-start except with the published Boolean @default(false) field on Post omitted because the scaffolded admin form wasn't coercing the string true or false from the input text field to the appropriate boolean value. (Subissue?)

There is no problem creating a User with the scaffolded admin form, but I get an error when I try to create a post for that user.

screenshot

There is, indeed, no authorId on the generated type PostCreateInput

export type PostCreateInput = {
  title: string
  content?: string | null
  author?: UserCreateOneWithoutPostsInput | null
}

defined in node_modules/.prisma/client/index.d.ts.

I produced the error following the following steps:

  1. Create a new app with yarn create redwood-app rw-test.
  2. Add Post and User to api/prisma/schema.prisma.
  3. Create migration and update: yarn rw db save then yarn rw db up.
  4. Scaffold admin forms for User and Post: yarn rw g scaffold user then yarn rw g scaffold post.
  5. Make a User through the admin form at http://localhost:8910/users/new. It should get id value 1.
  6. Try to create a post for that user at http://localhost:8910/posts/new. When you hit save, you should get the error in the screenshot.

I'm running macOS Catalina Version 10.15.4.

ps. Love the project!

All 13 comments

I can confirm this, ran into the same thing last night.

Hmmmmmm we have SDL generator tests in place that are checking this exact functionality: https://github.com/redwoodjs/redwood/blob/master/packages/cli/src/commands/generate/sdl/__tests__/fixtures/multiWordSdlCrud.js#L16-L19

I'll take a look tomorrow!

Actually....................................

I just read your actual issue (helps to do that!) and the type mismatch you're finding is in the files that prisma generates, not us... that's strange indeed. From first glance it looks like your prisma libraries were generated against a previous version of the schema, but the scaffolds were created against the current version (the scaffold does show an Author Id field).

What does your posts.sdl.js file look like? Does it show authorId as a possible input field?

You can run yarn rw db generate to re-create those prisma client libraries, try that and restart yarn rw dev to see if anything changes?

Tried the yarn rw db generate, but the issue persists. Here's the posts.sdl.js:

import gql from 'graphql-tag'

export const schema = gql`
  type Post {
    id: Int!
    title: String!
    content: String
    author: User
    authorId: Int
  }

  type Query {
    posts: [Post!]!
    post(id: Int!): Post!
  }

  input CreatePostInput {
    title: String!
    content: String
    authorId: Int
  }

  input UpdatePostInput {
    title: String
    content: String
    authorId: Int
  }

  type Mutation {
    createPost(input: CreatePostInput!): Post!
    updatePost(id: Int!, input: UpdatePostInput!): Post!
    deletePost(id: Int!): Post!
  }
`

@mgreenbe Check out your posts.js service. Specifically in the create method. You need to transform the authorId into the connect syntax that Prisma actually wants. For reasons I don't understand, they don't let you just edit foreign key columns like you can any other column in the table. I have an open issue with them about this: https://github.com/prisma/prisma/issues/2152

See the workaround here: https://github.com/prisma/prisma/issues/2152#issuecomment-621375111

TL;DR You need to strip authorId from your input object and instead use { author: { connect: { id: authorId } } }

@thedavidprice Remember when we talked about the scaffolds only half-working when trying to create foreign keys to other tables? This is that. I had that workaround that created the correct prisma syntax, but we took it out because we hoped we'd have a better solution soon...but then ever came up with one. 馃槓

Trying to imitate the workarounds from #prisma/prisma#2152. I changed createPost in posts.js to:

export const createPost = ({ input }) => {
  return db.post.create({
    data: { ...input, author: { connect: { id: input.authorId } } },
  })
}

Is this what you had in mind? Trying to create a new post, I now get the slightly different error

Screen Shot 2020-06-16 at 5 30 48 PM

I didn't regenerate the prisma client because I figured that would just overwrite this change?

@mgreenbe input will still have the authorId in there, you need to remove that completely. delete input.authorId will do it, even though it's kind of gross 馃槙

@cannikin Oh, I remember. This is the workaround, correct?

YUP! Why didn't we just put that in real Redwood again? 馃槄

@mojombo wanted a wrapper or something something -- scared of all the codes.

馃槈

@mgreenbe Hope that article helps! I'm not sure how to make it more "findable" for this situation, but I could edit the title or add some keywords if you think that would help others who run into this.

Oh yeah, kind of our own wrapper around db that we can do whatever we want with, but for most people it would be transparent and look like you're just using PrismaClient as usual. Someone should write that

@cannikin Replacing the auto-generated createPost in posts.js with

export const createPost = ({ input }) => {
  let data = { ...input, author: { connect: { id: input.authorId } } }
  delete data.authorId
  return db.post.create({ data })
}

worked. I can now create posts with the admin interface!

@thedavidprice Please adjust the title however you feel is best for findability of this workaround.

Thanks, all!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thedavidprice picture thedavidprice  路  3Comments

jeliasson picture jeliasson  路  3Comments

peterp picture peterp  路  4Comments

thedavidprice picture thedavidprice  路  3Comments

josteph picture josteph  路  3Comments