I'm at the end of the fourth phase of my coding boot camp. We previously learned about JavaScript, React, and Ruby. This phase focused on learning Rails, and we had to complete a full stack project utilizing React and Ruby on Rails. One of the concepts from this phase I'd like to dig into is the frontend to backend request response flow. This refers to data shared between a frontend JavaScript application and a backend API application. Rails will basically take an HTTP request and generate a properly-formatted response. I will use an example from my project.
1. Frontend Request
The process starts when the user interacts with the frontend and triggers an event, such as clicking a button or submitting a form. For example, the fetch request below is triggered when a user logs in. It sends a request to the endpoint /login
.
An HTTP request is sent to the backend API endpoint. POST is the HTTP verb in this request. The request contains information, such as the user's input, which is their username and password in this case.
function handleSubmit(e) {
e.preventDefault();
setIsLoading(true);
fetch("/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
}).then((r) => {
setIsLoading(false);
if (r.ok) {
setErrors([]);
r.json().then((user) => {
setUser(user);
navigate("/books");
});
} else {
r.json().then((err) => setErrors(err.error));
}
});
2. Backend Router
The backend Ruby on Rails server receives the request and routes it to the corresponding controller and action method contained in the routes.rb file. In the login route below, it's directing a POST request for the /login
endpoint to the sessions controller's create method.
post "/login", to: "sessions#create"
3. Backend Controller
The controller communicates with the model to access or create data via Active Record. The create method within the sessions controller below will find the instance of User in the database by username and save the user id in the session, unless the username or password are invalid.
def create
user = User.find_by(username: params[:username])
if user&.authenticate(params[:password])
session[:user_id] = user.id
render json: user, status: :created
else
render json: { error: "Invalid username or password" }, status: :unauthorized
end
end
4. Backend Model
If data is being created, the model will handle validations or return errors for invalid data. The User model in my project has validations to ensure a username is present, unique, and has at least two characters, and that the password is 2-8 characters long.
class User < ApplicationRecord
validates :username, presence: true, uniqueness: true, length: { minimum: 2 }
validates :password, length: { in: 2..8 }
end
5. Backend Database
Valid data will be located in the database. If data is being created, valid data will be persisted to the database as a new row in the corresponding table and assigned an ID value.
6. Backend Serializer
The serializer will determine which attributes will be returned in the JSON response rendered by the controller methods. My user serializer specifies that the username and user id will be returned in the JSON response. That way, only the necessary data is sent to the frontend.
class UserSerializer < ActiveModel::Serializer
attributes :id, :username
end
The server returns an HTTP response, which contains the JSON data, to the frontend. Using the login example, the user is now logged in and the process is complete!
Top comments (0)