What I wanted the app to do
The thought behind the app was simple. To create a repository for some of my favorite quotes from books I’ve read in the past few months. Because I wanted the app to have some CRUD functionality, the user should be able to:
- View all the book quotes currently in the database, including title, author, and genre information along with an image of the book cover
- Create new book quotes by filling in a form with the above information
- Delete book quotes
Setting up the models and controllers
For the Rails API, I kept with a pretty standard model structure. After creating the new Rails app (API only), I set up resources for three models — Quote, Author, Genre, comprising a “has-many-through” relationship, i.e. the quote is the join model between author and genre where authors have many quotes and many genres through quotes and where genres also have many quotes and authors through quotes. I was taught this helpful expression to show the relationship: Author -< Quote >- Genre.
Because I anticipated making several asynchronous requests from the frontend to the Rails API, I needed to make sure there were appropriate routes set up in controllers for the models.
First, I know that I need to see all of my quotes and need the ability to create new quotes, so I set up index and create routes in my Quotes controller. I set up a destroy route in the controller so that I can delete quotes as well.
There are a limited number of genres that the user will be able to select from a dropdown to associate with a new quote, so nothing special to do there. But, for the author, the form will have a text field to accommodate new authors. To address the need to create a new author, I create an author as the same time I create the quote.
Building out the frontend
To create the frontend for the app, I start with a basic scaffolding of HTML and CSS. I make sure that my HTML has a container with an id attribute for the all the quotes that will need to be populated to the page.
For example, when populating the quotes to the page, I first created a Quote class, containing a constructor function to build a JS quote object from the object fetched from the backend and also a render function to render the quotes to the page. Fetching the quote objects, looping through each quote object, and rendering the quote objects were separated into their own functions. I find that this kind of modularization helps with debugging as I step through the process of grabbing the quotes from the backend and making them show up on the page.
I know that some developers like to use HTML syntax as a string inside their JS files and then using the insert adjacent HTML method. I prefer to work directly with JS built-in methods for building and manipulating the DOM. Here’s my quote object, containing a constructor function and a render method that populates the quote “cards” in the DOM:
We got issues, y’all
In the end, I was able to put together a simple and clean book quotes application, all contained on one page. But, because it was a one-page application, I ran into a troublesome issue — how do I present the new quote form to the user?
I had a few options. First, I could make the form static and include it somewhere on the page. No page location felt right and the form just seemed to clutter the app. I also thought about doing something similar to some coding examples I had seen, and include the form in the page HTML but set its display property to “none”. The user would then just click a button to have the form slide down into the page at the top. Better, but it still felt clunky.
In the future, I’m planning to return to the application to add additional functionality. For example, adding the ability to like or comment on quotes. With the social component, I might also add some authentication/authorization to create user accounts and restrict certain functionality based on the account created.