В Модуле 4 курса инженера-программиста с частичной занятостью в школе Flatiron нам нужно разработать проект, используя Rails в качестве серверной части и JavaScript в качестве внешнего интерфейса приложения.

Идея моего проекта заключалась в возможности поработать над тем, что изначально заставило меня начать Bootcamp. Объедините свои знания в области маркетинга с программированием. Захватывающая часть заключается в том, что этот проект может быть реальным случаем проекта.

Это викторина типа личности, ориентированная на агентов по недвижимости, которые хотели узнать, какой тип / уровень они в настоящее время находятся в этой отрасли. Им нужно заполнить несколько форм личной информации на первой странице и ответить на 6 вопросов на второй странице, чтобы получить результат на основе их ответов.

Они могут быть «экспертом», «мастером» или «топовым» агентом. Каждый результат содержит информацию о нем, предложения продуктов, которые могут помочь им в карьерном росте, бесплатный контент и специальный промо-код, который они могут использовать для покупки предложенных продуктов.

Компания, которая продает маркетинговые материалы агентам по недвижимости, может использовать это приложение, чтобы получить потенциальных клиентов, лучше узнать свою аудиторию, использовать собранные данные, повысить узнаваемость и продажи продукта.

Важная функция, которую мне нужно было иметь в моем проекте, заключалась в следующем: запустить базу данных/модель пользователя с необязательным результатом (метод создания), а после того, как пользователь завершил тест, обновить таблицу результатов пользователя. Вот как я обработал методы создания пользователя (POST) и обновления (PATCH).

Что касается серверной части: начиная с создания пользовательской базы данных, я установил для отношения принадлежности_to null значение 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

(Я не осознавал этого, когда впервые создал базу данных, поэтому мне пришлось изменить этот столбец после некоторых ошибок):

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

Внутри модели User добавьте belongs_to :realtor_level, optional: true, чтобы не возникало ошибок, когда пользователь заполняет начальную форму (первую страницу) не заполнив результат. Я также добавил метод для поиска текущего пользователя.

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

Внутри user_controller добавьте методы index, create, update и private params. Я использовал .find_or_create_by на случай, если пользователь вернется, чтобы пересдать викторину. Таким образом, база данных найдет адрес электронной почты пользователя и обновит его результат.

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

Сериализатор (с использованием active_model_serializers):

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

Во внешнем интерфейсе: внутри класса RealtorLevel (имя класса, в котором я отображаю результаты) есть функция конструктора, функция рендеринга для отображения результата и этот метод для обновления базы данных.

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

Внутри метода класса UserApi у меня есть запрос на выборку POST для сохранения личной информации пользователя в базе данных.

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();
 };

Запрос PATCH, который может обновить результат и другие пользовательские данные, если таковые имеются.

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))
 };
};

Аргумент результата внутри updateUserResult(result)является тем же аргументом результата, который был получен из userCall.updateUserResult(User.currentUser.result)внутри функции updateDatabase.

UserCall и входные переменные были объявлены внутри файла index.js.

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");

Таким образом, информация из базы данных пользователей является точной и доступной для компании, чтобы получить и использовать ее.