Project 4: A Personal Library
Project 4 for my coding bootcamp is underway and it is super fun. This time, I am building a full stack SPA with the following requirements:
As always, when approaching a project, I try to come up with something that I would use. In my free time, I really enjoy reading. I thought creating an online library could be a fun way to meet these requirements.
At this point in my work, I meet all of the above requirements except for the many-to-many relationship. Unfortunately, I overlooked this requirement and went full steam ahead on a simpler SPA. I made the following walkthrough video of where my app is currently in production:
Moving forward, I need to add the many-to-many relationship. Join me as I walk step-by-step through this process.
Step 1 Add the new model and adjust tables
To make this process as easy as possible, I used Rails Generators whenever I could. To add the new model and controller:
Next, I needed to do some migrations to adjust the tables already in the backend. Mainly I needed to add the new foreign key to the books table so it could become a joint table. I also wanted to change some of the column names. Although I followed naming conventions, some of the column names were unnecessarily long. Since I was already adjusting the table, I took this opportunity to rename a few columns in the same migration:
With those migrations complete, my schema now looks like this:
In the books table, there is a column for user_id and for category_id. These two foreign keys refer to the users table and categories table. With these keys in place, each instance of a book will need to be owned by a user AND owned by a category. Therefore, each book can be used to connect a user to their categories. The books table acts as a joint table.
Step 2 Registering Routes
My next step was to register the new routes I would need. In routes.rb in the config folder, I declared my routes. All users have access to all categories and all books are required to have a category. Therefore, I want users to be able to read the categories and add to them, but they cannot delete or edit them.
Categories are globally owned and utilized. If User A could delete a category that User B was relying on it would cause User B’s library to no longer function correctly. As such, the only routes I want to have for resources are index and create.
With those routes established and registered, I needed to set up the categories_controller.
The index method will show ALL of the categories available. (In this way, a user can add a book to a category even if they are not the person to create the category). And the create method allows a user to create a new category for books.
Under the private section, I also created an authorize method. This method establishes that a user is logged in before it will authorize someone to view the data.
Step 3 Adjusting the frontend
Once those changes were in place for the backend, I had to go through the frontend and adjust for the new names. I also added a fetch to my context to get all of the categories to the frontend.
As I established above, I registered my index route so this fetch renders all of the categories from the backend and not just those owned by the user. Because a user can add books to any category, they need to have access to all of them. I also created a form for the front end so that a user can add a new category if they so chose. This new category would then be accessible by all users.
With all of the above in place, my backend now has a many-to-many relationship and my frontend has the ability to view and add to that relationship.
Please check out this walkthrough video of where the app is now.
Beyond the Project
Moving forward, I have the following ideas to add to this project to make it even move useful.
- many-to-many relationship where each book can belong to a series. (I would need to create an initial N/A instance for any books that are not part of a series.) I think it would be beneficial to group books together in this way.
- one-to-many relationship where each book can have multiple notes. Notes would have book_id (foreign key), section_title, and information. I could envision notes rendering on the books show page. This feature could be used for making notes per chapter/section of the book. I could see students utilizing this to organize and study.
- one-to-many relationship where each book can have multiple characters. Characters would have book_id (foreign key), name, description, etc. This would also render on each books’ show page. Again this could be used for studying and organizing information.