All right, this is enough intro. Now let’s dive into details. Since there are lots going on I will try to keep it as simple and less confusing as I can. So basically, I created a library app that allows users to store their favorite books and perform CRUD actions on their book collection.
As I mentioned before, the configuration of an API on rails was really easy. All you need to do is typing rails new your_api — API command in your terminal and Rails does the rest for you.
As a requirement, we had to handle Client/Server interaction in JSON format which means I had to set up my controllers in JSON. I will come back to JSON format again but first I want to go through my controller actions real quick. In my previous Rails project, the controllers were playing an important role in my application but this time since we were asked to build a simple SPA there is not much going on in my controllers. Basically, I do have an index, create and destroy actions in my books_controller and index and show actions in my categories_controller. That was enough for me to demonstrate CRUD actions on my app. All of my actions are rendering in JSON format. There are two ways to render your data in JSON format. In my case, since it wasn’t a large scale app, I was able to render my data by specifying JSON in my controller action as below.
But if you have more models in your app, things might get complicated. In that case, you might consider using serializers to extract your data from a service class. With the help of serializers, you can easily customize your data in JSON format. You can separate the data you want to see in JSON easily by using serializers. There is even a gem to set up service classes. It’s called FAST JSON API gem. After you installed that gem, all you need to do is typing
rails g serializer “your model”
in your terminal and then you will be all set.
PS: If you choose to extract your data from service classes, you will have to make some slight changes in your controller's actions as well. You will need to instantiate the data belongs to that particular model by using serializers as below.
class CategoriesController < ApplicationController def show
@category = Category.find(params[:id])
render json: CategorySerializer.new(@category)
In total, I do have 2 models. Book and Category. And as you can see below Book belongs_to Category and Category has_many books.
I used sqlite3 as a DB choice in this project too. Additionally, I dumped some fake data in my seed file to test my API and see some actions on the frontend.
API SERVICE CLASS
This is where I make my fetch requests to the API I built on Rails. The requests are pretty straight forward. You just gotta follow the convention. The things get a bit different though when you make a fetch request to your API when you want to modify/process data(PATCH, DELETE, AND POST). You have to make sure you specify the type of your request in your fetch. If you are planning to create new data, the method should be POST. If you are planning to update your data, it’s gotta be PATCH and so on. Normally, in a fetch request you get the response from your API first, I think we can call it raw data. And as a second step, you have to parse it into JSON format in your first .then. And then you will be able to play with that data. I mostly use that JSON formatted data in my index.js file where I manipulate the DOM. Separation of concerns is real.
First off, you should know that when you are working on the frontend that means you are working with HTML elements. That’s why you should consider your JS classes as a part of the HTML element. This category dropdown is a category dropdown, it’s not the category model on my backend. Make sure you understand that first. Otherwise, things will become fuzzy for you. I am saying this based on my experience. Of course, it contains your category model attributes but in fact, you are just building a dropdown menu based on the names of your categories. Also, this is where these static methods and class constructors come into play. I have one static method called categoryCollection. The good thing about these static methods is you can them directly on the class. And for the constructors, I think you can take them as a cell that contains a bit of information about your object from the beginning. And you assign that information to something called “this”. Think of “this” as a reference to the object it is inside.
Pretty much the same goes for my BookCard class. The important thing to note here is -it applies to my category dropdown class too- instead of passing an HTML block in my functions, I decided to render my stuff by using built-in JS methods. Like I needed to render a div element for each book card, instead of passing something like
<div class="each-book"> </div>
I used those built-in methods as below. For me, it was easier to read this way. But I do see other students choosing to render their innerHTML as I mentioned above.
let eachBookDiv = document.createElement('div');
For this class though, I had to create my form element by passing the whole HTML block in my function. Because I was having problems getting the right value from my select options when selecting a category. (event.target.value) Getting the right value was important because I do filter my books based on a category. So getting the right category id was crucial.
I did use Bootstrap and FontAwesome but additionally, I also wrote some CSS as below.