How to deal with two foreign keys when creating a join table item.
This blog will discuss one method for creating an item in a database join table within a Single Page Application built using React Frontend, Rails Backend, PostgreSQL database, and Active Record Associations.
What is the problem?
Items in a join table need to be associated with two different models, requiring each item to have two foreign keys. Creating the item within one of the parent models automatically includes the foreign key assigned to that parent model, however, adding the foreign key for the other parent table is not automatically added, regardless of the associations.
Consideration #1: Does your item have space for two foreign keys?
When you are creating the table for the join table, you need to make sure that within that table is space for the foreign keys for both parent tables.
Consideration #2: Where should the item be created?
Knowing that the item has two parent tables to which it is association, consideration must be taken as to where the item is created in the front end so that the creation makes sense.
For example, in a join table of QUESTIONS that belong to both a USER and a COURSE, it makes sense that either parent could be used. Other situations may warrant different approach, but for now we can just choose to create a question under the USER and then associate it to the COURSE.
Here is an image that reflects the intended connections for the project, with a focus on the QUESTION table, which functions as the join.
You can see that the QUESTION table uses the user.id to connect to the USER table and the course.id to connect to the COURSE table.
Step #1: Accessing the foreign key(s)
As mentioned above, for creating the QUESTION under the USER model, the foreign key for the USER will already be included. However, we need to gain access to the foreign key for the COURSE to which the QUESTION is associated.
With a list of the courses already held in state, one solution is to make a drop-down list of the courses within the controlled form for creating the new question.
We would store that selected course in state, so adding state for the course on the form page is needed.
In order to make the drop-down list, you can use the information from the courseList array that is stored in state. Make sure to pass down the state variable, in this case courseList, down as a prop to the correct component, in this case that is where you are making this form.
From here you can create a variable that holds the drop-down option elements to be used in the form, made for each class by mapping over the courseList and storing the course.id as the value.
Storing the course.id as the value is very important as this value is what will be used to add the course.id to the QUESTION when posting to the database.
Now that you have the courses as options, you can use the variable that holds this information in the form for making a new question.
Step #2: Saving the Foreign Key
When doing so, you will need to make sure that the selected course’s value will be saved in state to be used for the QUESTION post. Adding a “selectCourse” function to the onChange event will ensure that when an item from the drop-down is selected, that value (in this case that course’s course.id) will be stored. The selectCourse functions is simple as it only is used to update state.
Once your form is complete, you will have a submit function that will need to include a POST request to create the question.
Step #3: Writing the POST Request
Within the POST request is where you use the value stored in the course state, which is the course.id, and include that in the information that will be used to construct the QUESTION object.
You can see in the image above that the course.id will be added as the second foreign key to the object and the first foreign key, in this case the USER, will be added based on the routes of the POST request in the backend (shown below) because the question is being created as a child of the user.
For reference: the question_params are created via a function below. It is important to note that :course_id is a parameter of the original join table (see Consideration #2).
Once completing all of these steps you should be able to find that your join tables item (in the example, a new question) was successfully created and contains the foreign key to the other parent table (in this case the COURSE).
One last thing to remember is that this is sequence of steps is just for creating the item on the server side. Remember to also update the frontend state so that you can use the new question in your application.
Not sure how to do that? Check back soon for a tutorial on updating Front End state with React.