Автор оригинала: Osinachi Chukwujama.
Привет, добро пожаловать в 4-й учебник в серии. В предыдущем уроке мы создали методы Crud для модели курса. Если вам понравится пропустить предыдущие шаги, клонировать репо и оформить заказ к Курсы-грубые и отношения Филиал, затем код вместе.
Вычисляя совокупность
Целью этой API является вычисление студенческого CGPA. Существует несколько различных систем для вычисления CGPA. Для этого учебника мы будем придерживаться систем 4 и 5 точек.
4 точечная система
Система 4 точек следует за этим отображением
A | 4 |
B | 3 |
C | 2 |
D | 1 |
F | 0 |
5 точечная система
И то, что из 5 баллов системы:
A | 5 |
B | 4 |
C | 3 |
D | 2 |
F | 0 |
Теперь, если бы мы вычислим CGPA студента, учитывая эти детали
const courses = [ { code: "MTH 304", grade: "B", credit_load: 4, }, { code: "GSW 102", grade: "A", credit_load: 3, }, { code: "VEY 201", grade: "D", credit_load: 1, }, { code: "WOR 423", grade: "F", credit_load: 2, }, ];
Мы будем следовать этому алгоритму
let total_grade_point = 0 let total_credit_load = 0 for (course of courses){ total_grade_point += course.grade * course.credit_load total_credit_load += course.credit_load } const cgpa = total_grade_point/total_credit_load
Если вы заметите total_grade_point.grade * curot.credit_load
имеет умножение строки и количества. Нам нужен способ конвертировать. Как таблица поиска. Мы можем либо сохранить эту таблицу в нашем коде или базе данных. Мы пойдем с позже. Это то, где появляется посева. Мы будем осевать таблицу поиска с данными. Мы назовем этот поиск таблицы GORT_SYSTEMS.
Модель градиастема
Начните с создания модели и ее миграции.
adonis make:model GradeSystem -m
В файле миграции GORD_SYSTEM_SCHEMA добавьте эти два разных колонны.
table.integer("point").notNullable(); ["A", "B", "C", "D", "E", "F"].map((grade) => { table.integer(grade).unsigned(); });
Вы можете удалить table.timestamps ()
Определите, чтобы сделать ваш стол очистителя. Если вы его удалите, добавьте эти статические GetTers на ваш Грейссистема
модель. Узнать больше от Документы Отказ
static get createdAtColumn() { return null; } static get updatedAtColumn() { return null; }
Градсистемный севенец
Создайте сеялку с помощью CLI.
adonis make:seeder GradeSystem
Затем добавьте заменить содержимое Gradesystemseeder.js с этим:
"use strict"; const GradeSystem = use("App/Models/GradeSystem"); class GradeSystemSeeder { async run() { const points = [4, 5]; for (let point of points) { const system = new GradeSystem(); system.point = point; ["A", "B", "C", "D"].map((grade, index) => { system[grade] = point - index; }); system["F"] = 0; await system.save(); } } } module.exports = GradeSystemSeeder;
Теперь запустите ожидающую миграцию и одновременно семяте базу данных.
adonis migration:run --seed
Пользовательские настройки
Поскольку мы не будем знать по умолчанию WALL_SYSTEM наших пользователей, нам нужно дать им возможность изменить его. Мы сделаем это в предпочтениях. Во-первых, мы создадим модель и миграцию.
adonis make:model Preference -m
Добавьте это определяет миграцию.
table .integer("grade_system_id") .unsigned() .references("id") .inTable("grade_systems") .onUpdate("CASCADE") .onDelete("SET NULL"); table .integer("user_id") .unsigned() .nullable() .references("id") .inTable("users") .onUpdate("CASCADE") .onDelete("CASCADE");
Они в основном внешние ключей, которые указывают на таблицы GORD_SYSTEMS и пользователей. Предпочтения и градуссистемные модели имеют отношения 1: 1. Это имеет смысл сказать, что предпочтение карты к градусистеме. Это означает, что мы определим отношения в модели предпочтения.
// inside Preference.js gradeSystem() { return this.belongsTo("App/Models/GradeSystem"); }
Чтобы получить градусистему предпочтения, мы просто делаем
await preference.gradeSystem().fetch()
Кумулятивная модель
Мы вернемся к совокупности. Продолжай и создайте модель и файл миграции.
adonis make:model Cumulative -m
Добавьте эти контактные элементы столбца в кумулятивный файл миграции.
table.integer("credit_load").unsigned(); table.integer("grade_point").unsigned(); table.decimal("grade_point_average", 20, 2).unsigned(); table .integer("user_id") .unsigned() .nullable() .unique() .references("id") .inTable("users") .onUpdate("CASCADE") .onDelete("CASCADE");
Мы устанавливаем точность 2 десятичных знаков до GORD_Point_average с максимальной длиной 20 символов. Запустить миграцию.
adonis migration:run
Теперь, когда у нас есть настройки и кумулюбительные таблицы, мы можем справиться с отношениями. Когда пользовательские регистрируются, мы хотим инициализировать строку на кумулятивных и предпочтениях таблиц. Для этого мы создадим модели и связываем их с помощью модели пользователя. Во-первых, требуют этих моделей.
const Preference = use("App/Models/Preference"); const GradeSystem = use("App/Models/GradeSystem");
Затем создайте новый экземпляр каждой модели в методе регистров usercontroller.
const preference = new Preference(); const cumulative = await Cumulative.create({ credit_load: 0, grade_point: 0, grade_point_average: 0, });
Имеет смысл собирать предпочтительную систему оценки пользователя во время регистрации. Итак, давайте сделаем это дополнительное поле. Добавить GORT_SYSTEM
к вашему Запрос. Все ()
так что это становится этим
const { email, password, grade_system } = request.all();
В правилах добавьте правило Enum для GORD_SYSTEM
const rules = { email: "required|email|unique:users,email", password: "required", grade_system: "in:4,5", };
Сохраните необходимый экземпляр WARL_SYSTEM к переменной Градсистемное существо
Отказ Если система оценки не предоставлена, мы устанавливаем его как 5.
const gradeSystemInstance = await GradeSystem.findBy( "point", grade_system | "5" );
Обратите внимание, что мы не использовали Запрос ()
Чтобы найти этот экземпляр. Findby
является статическим методом ясного модели. Узнать больше от Документы Отказ
Так как мы уже определили взаимосвязь между предпочтением и градусистом как
// App/Models/Preference.js gradeSystem() { return this.belongsTo("App/Models/GradeSystem"); }
Мы будем использовать ассоциировать
связать их.
// UserController.js register() method await preference.gradeSystem().associate(gradeSystemInstance);
ассоциировать
используется на Приятно
Отказ Узнайте больше о ясных отношениях от Документы Отказ
Последнее осталось связать совокупные и предпочтения экземпляры пользователю. Поскольку они оба 1: 1 отношения, мы будем использовать Hasone
определить их. Внутри Приложение/Модели/user.js
добавьте эти методы
cumulative() { return this.hasOne("App/Models/Cumulative"); } preference() { return this.hasOne("App/Models/Preference"); }
Теперь в методе регистрации мы будем использовать сохранение вместо ассоциирования для регистрации зарубежных ключей.
await user.preference().save(preference); await user.cumulative().save(cumulative);
Правило большого пальца – использовать сохранение с
- ассортимент
- Hasmany И используйте ассоциировать при использовании обратного от HASONE I.E.
Приятно
Отказ Пожалуйста, обратитесь к Документы Для получения дополнительной информации о отношениях.
Кумулятивный контроллер
Создайте кумулятивный контроллер, запустив это
adonis make:controller Cumulative --type=http
Нам нужны два метода. Один для возврата вычисленного CGPA и другого для вычисления CGPA. Мы будем использовать запрос на получение первого и запроса на патч на второй. Добавьте эти маршруты на маршруты.
Route.get("cumulative", "CumulativeController.show").middleware(["auth"]); Route.patch("cumulative", "CumulativeController.update").middleware(["auth"]);
Первые вещи сначала для контроллера, мы импортируем совокупную модель. Мы также добавляем модели курса и предпочтений, потому что мы будем использовать их.
// CumulativeController.js const Cumulative = use("App/Models/Cumulative"); const Course = use("App/Models/Course"); const Preference = use("App/Models/Preference");
Теперь, для получения запроса, мы просто возвращаем кумулятивную. Так что наш метод будет
async show({ auth, response }) { try { const user = await auth.user; const cumulative = await Cumulative.findBy("user_id", user.id); return response.status(200).send(cumulative); } catch (error) { return response.status(500).send(error); } }
Зарегистрируйте новый пользователь и попробуйте!
Запрос на патч более вовлечен. Сначала мы рассчитаем совокупность перед сохранением и возвращением его. Мы начнем, найдя кумулятивную и оценочную систему пользователя.
async update({ auth, response }) { try { const user = await auth.user; const cumulative = await Cumulative.findBy("user_id", user.id); const preference = await Preference.findBy("user_id", user.id); const grade_system = await preference.gradeSystem().fetch(); } catch (error) { console.log(error); return response.status(500).send(error); } }
Затем мы запрашиваем курсы пользователя
// update method: CumulativeController.js const raw_courses = await Course.query() .where("user_id", user.id) .fetch(); const courses = raw_courses.toJSON();
После этого мы вычисляем total_credit_load
. и total_grade_point
Отказ
// update method: CumulativeController.js const total_credit_load = courses.reduce((accumulator, course) => { return accumulator + course.credit_load; }, 0); const total_grade_point = courses.reduce((accumulator, course) => { return accumulator + course.credit_load * grade_system[course.grade]; }, 0);
Наконец, мы заменяем существующие кумулятивные значения при вновь вычисленных значениях, упорствуйте его в БД и вернуть совокупность.
// update method: CumulativeController.js cumulative.credit_load = total_credit_load; cumulative.grade_point = total_grade_point; cumulative.grade_point_average = Number( (total_grade_point / total_credit_load).toFixed(2) ); await cumulative.save(); return response.status(200).send(cumulative);
Вот ответ запроса на патч.
Вот и все. Ты сделал это. Мы сделали! Поздравляю с этим далеко. Мы что-то посмотрим? Как мы можем быть уверены, что весь код, который мы написали до сих пор, не сломаются в производстве 🤔? Есть только один способ быть уверенным. Мы пишем тесты!
Реконструировать
Прежде чем мы продолжим писать тесты, давайте рассмотрим то, что мы узнали в этом руководстве.
- Как создать сеялку
- Как бежать миграции и семена одновременно.
Спасибо за следующее вместе. В следующем руководстве мы напишем функциональные тесты для наших API. Спасибо за следующее вместе. Adios ✌🏾🧡.