Creating and Updating User Database — JavaScript Frontend, Rails Backend

Luciana
4 min readOct 3, 2021

In Module 4 of the part-time Software Engineer course at Flatiron School, we need to develop a project using Rails as the backend and JavaScript as the frontend of the application.

My project idea was an opportunity to work on what initially made me start the Bootcamp. Combine my marketing knowledge with coding. The exciting part is that this project could be a real-world project case.

It’s a personality type of quiz focused on real estate agents that wanted to know what type/level they currently are in this industry. They need to fill up a few personal information forms on the first page and answer 6 questions on the second page to get the result based on their answers.

They can be an “expert”, a “master”, or a “top” agent. Each result has information about it, product suggestions that can help grow their careers, free content, and a special promo code that they can use to buy the products suggested.

A company that sells marketing materials to real estate agents could use this application to get leads, to know better their audience, use the data collected, increase visibility and product sales.

An important feature that I needed to have in my project was: start the User database/model with the result optional (create method) and after the user completed the quiz, update the User result table. Here is how I handled the User create (POST) and update(PATCH) methods.

On the backend: Starting on the User Database creation, I set up the belongs_to relationship null to true.

class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :email
t.boolean :has_account
t.string :result
t.belongs_to :realtor_level, null: false, foreign_key: true
t.timestamps
end
end
end

(I didn’t realize it when I first created the database so I had to change this column after getting some errors):

class ChangeUsersColumnNull < ActiveRecord::Migration[6.1]
def change
change_column_null(:users, :realtor_level_id, true)
end
end

Inside the User model, add belongs_to :realtor_level, optional: true this way it won’t have any errors when the user fills up the initial form (first page) with doesn’t fill the result. I also added a method to find the current user.

class User < ApplicationRecord
belongs_to :realtor_level, optional: true
def self.current_user
current_user = User.last
end
end

Inside the user_controller add the index, create, update, and private params methods. I used the .find_or_create_by in case the user come back to retake the quiz. This way, the database will find the user’s email and update their result.

class UsersController < ApplicationController def index
users = User.all
render json: users
end
def create
user = User.find_or_create_by(email: params[:email])

if user
render json: user
else
render json: { error: user.errors.full_messages, message: "Something went wrong." }
end
end
def update
user = User.find_by_id(params[:id])
if user.update(user_params)
render json: user
else
render json: { error: user.errors.full_messages, message: "Something went wrong." }
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :has_account, :result)
end
end

The serializer (using the active_model_serializers):

class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :email, :has_account, :result
belongs_to :realtor_level
end

On the frontend: Inside the RealtorLevel Class (class name that I’m displaying the results), there’s the constructor function, a render function to display the result and this method to update the database.

class RealtorLevel {static updateDatabase() {
userCall.updateUserResult(User.currentUser.result)
}
RealtorLevel.updateDatabase()
}

Inside the UserApi class method, I have the POST fetch request to save the user personal information in the database.

class UserApi {
constructor(port) {
this.port = `${port}/users`;
};
createUsers() {
const userInfo = {
first_name: firstNameInput.value,
last_name: lastNameInput.value,
email: emailInput.value,
has_account: hasAccountInput.checked,
};
const configObj = {
method: 'POST',
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(userInfo)
};
fetch(this.port, configObj)
.then(resp => {
if (resp.ok) {
return resp.json()
} else {
throw new Error()
}
})
.then(data => {
if (data.result !== null) {
let level;
if (data.result === "Expert") {
level = data.result
} else if (data.result === "Master") {
level = data.result
} else if (data.result === "Top Agent") {
level = data.result
}
realtorLevelCall.getResult(level);
};
const user = new User(data);
})
.catch(error => console.log(error))
quizDiv.appendChild(quizContainer);
questionCall.getQuestions();
};

A PATCH request that can update the result and the other user inputs, if any.

updateUserResult(result) {
const updateUser = {
first_name: firstNameInput.value,
last_name: lastNameInput.value,
email: emailInput.value,
has_account: hasAccountInput.checked,
result: result,
}
const configObj = {
method: 'PATCH',
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(updateUser)
}
fetch(`${this.port}/${User.currentUser.id}`, configObj)
.then(resp => resp.json())
.then(data => {
console.log(data)
})
.catch(error => console.log(error))
};
};

The result argument inside the is the updateUserResult(result)is the same result argument that came from userCall.updateUserResult(User.currentUser.result)inside the updateDatabase function.

The userCall and the input variables were declared inside the index.js file.

const userCall = new UserApi(port);
const firstNameInput = document.getElementById("user-first_name");
const lastNameInput = document.getElementById("user-last_name");const emailInput = document.getElementById("user-email");
const hasAccountInput = document.getElementById("user-has_account");

This way, the User database information is accurate and available for the company to retrieve and use it.

--

--