Tom Yotwongjai
Tom Yotwongjai

Reputation: 67

How to create a connection with already existing entity in prisma many to man relation

Currently I have a prisma model:

model Student {
  id             Int     @default(autoincrement()) @id
  firstName      String  
 lastName       String
  classes        CourseEnrollment[]
}

model Class {
  id             Int     @default(autoincrement()) @id
  name           String
  courseDetails  String?   
  members        CourseEnrollment[] 
}

model CourseEnrollment {
  studentId      Int
  student        Student  @relation(fields: [studentId], references: [id])
  classId        Int
  class          Class   @relation(fields: [classId], references: [id])
  @@id([studentId, classId])
}

It's a many to many relation which a class can have many students and a student can have many classes. I want to add edit functionality on my form on a client side with an option of assign an already existing class to a student. I am targeting each value and able to cosole log a new edit value with an id of the class I want to assign.

Handle edit function:

const EditStudent = ({ closeModal, student }) => {
const [firstName, setFirstName] = useState(student.firstName);
const [lastName, setLastName] = useState(student.lastName);
const [classItem, setClassItem] = useState(student.classes.id);
const [classData, setClassData] = useState([]);

const id = student.id;
const updateStudent = {id, firstName, lastName, classItem};


const handleEditStudent = async (e) => {
    e.preventDefault();
    console.log(updateStudent);

    }

Console log result: //Each values are correctly logged

{id: 72, firstName: 'John', lastName: 'James', classItem: '25'}

My form:

<form>
<input type="text" id="firstName" name="firstName" defaultValue={student?.firstName} onChange={(e) => setFirstName(e.target.value)} />
<input type="text" id="lastName" name="lastName"  defaultValue={student?.lastName} onChange={(e) => setLastName(e.target.value)}/>

   //Mapping through classes use have created

<select name="course" id="course" onChange={(e) => setClassItem(e.target.value)}>
 <option value="class">Select a class</option>
 {classData.map((classData) => (
 <option key={classData.id} value={classData.id}>
  {classData.name}
 </option>
    ))}
 </select>
</form>

I read through another stackoveflow that stated to create a connect I tried to manually edit a student and added class id which successfully edit student name and connect existing class with that id:

const updateStudent = await prisma.student.update({
        where: {
            id:72
        },
        data: {
          firstName: "John",
          lastName: "James",
          classes: {
               create: {
                class: {
                    connect: {
                        id: 25
                    }
                }
               }
             }
          }
    })

So I did as follow and tried to implement it on the client side:

My current edit endpoint:

const {id, firstName, lastName, classItem } = req.body;
try{
    const updateStudent = await prisma.student.update({
        where: {
            id: id
        },
        data: {
          firstName: firstName,
          lastName: lastName,
             classes: {
                create: {
                    class: {
                  connect :{id: classItem } 
                }
               }
             }
          }
    );
 res.status(200).json(updateStudent);
    console.log(updateStudent);
} catch (error) {
    console.log(error);
}

Handle edit function to edit data on the client side:

const EditStudent = ({ closeModal, student }) => {
const [firstName, setFirstName] = useState(student.firstName);
const [lastName, setLastName] = useState(student.lastName);
const [classItem, setClassItem] = useState(student.classes.id);
const [classData, setClassData] = useState([]);

const id = student.id;
const updateStudent = {id, firstName, lastName, classItem};


const handleEditStudent = async (e) => {
    e.preventDefault();
     try{
        const response = await axios.put(`/api/student/edit`, updateStudent);
        console.log(response);
        window.location.reload();
        }catch (error) {
        console.log(error);
      }  
      console.log(updateStudent);
      }

I am getting the following error:

Invalid `prisma.student.update()` invocation:
where: {
  id: 72
},
 data: {
 firstName: 'John',
lastName: 'James',
classes: {
 create: {
 class: {
  ~~~~~
  connect: {
 id: '25'
  }
  },
 classId: Int
  }
Unknown arg `class` in data.classes.create.class for type CourseEnrollmentUncheckedCreateWithoutStudentInput. Did you mean `classId`?

Argument classId for data.classes.create.classId is missing.

I tried to change to classId but still getting the same error. Does anyone know what this error mean or if I am missing something on my prisma update?

Upvotes: 1

Views: 1308

Answers (1)

Tom Yotwongjai
Tom Yotwongjai

Reputation: 67

So I actually found a solution to this. When I check my error again, I notice that my class id is a string which would be the reason why Prisma could not recognize the id itself. After doing some research I found a javascript function parseInt() which turn string into integer which I had done during codewar challenge from before. Not sure why my class id is not an integer, I will have to check my model again but this work.

const updateStudent = await prisma.student.update({
        where: {
            id: id
        },
        data: {
          firstName: firstName,
          lastName: lastName,
             classes: {
                create: {
                 class: {
                        connect: {
                            id: parseInt(classItem) //this is all it need
                        }
                    }

Upvotes: 1

Related Questions