Дикий Григорий

Full-stack веб-разработчик

API на Node.JS: Модели. Часть 4

Для работы с данными нужно создать модели. На данный момент в файле models/tasks.js находится статичная модель, то есть отдается статичный Json. Для того, чтобы получить динамически данные нужно использовать Sequelize модели. У нас будут модель пользователя и модель задачи, причем отношения между ними будут один ко многим. Опишем сначала модель задачи:

module.exports = (sequelize, DataType) => {
  const Tasks = sequelize.define("Tasks", {
    id: {
      type: DataType.INTEGER,
      primaryKey: true,
      autoIncrement: true
    },
    title: {
      type: DataType.STRING,
      allowNull: false,
      validate: {
        notEmpty: true
      }
    },
    done: {
      type: DataType.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  }, {
    classMethods: {
      associate: (models) => {
        Tasks.belogsTo(models.Users);
      }
    }
  });

  return Tasks;
};

В данной модели мы создали следующие типы данных:

  • id: поле для счетчика
  • title: название задачи
  • done: флаг отвечающий за выполнение задачи

Для связи с моделью User используется объект classMethods, где указана связь один пользователь - много задач.

Теперь когда уже создана модель задачи, создадим модель пользователя models/users.js:

module.exports = (sequelize, DataType) => {
  const Users = sequelize.define("Users", {
    id: {
      type: DataType.INTEGER,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataType.STRING,
      allowNull: false,
      validate: {
        notEmpty: true
      }
    },
    password: {
      type: DataType.STRING,
      allowNull: false,
      validate: {
        notEmpty: true
      }
    },
    email: {
      type: DataType.STRING,
      allowNull: false,
      unique: true,
      validate: {
        notEmpty: true
      }
    }
  }, {
    classMethods: {
      associate: (models) => {
        Users.hasMany(models.Tasks);
      }
    }
  });

  return Users;
};

Данная модель состоит из следующих полей:

  • id: поле для счетчика
  • name: имя пользователя
  • password: пароль пользователя
  • email: электронная почта пользователя

Связь с моделью Tasks происходит в классе classMethods через конструкцию Users.hasMany(models.Tasks). Теперь нам надо убедится, что config.js загружается раньше чем db.js, то есть index.js из корневой директории должен выглядеть так:

import express from "express";
import consign from "consign";

const app = express();

consign()
  .include("libs/config.js")
  .then("db.js")
  .then("libs/middlewares.js")
  .then("routes")
  .then("libs/boot.js")
  .into(app);
Стоит заметить, что мы убрали загрузку моделей при помощи consign, так как она будет происходить в db.js:
import fs from "fs";
import path from "path";
import Sequelize from "sequelize";

let db = null;

module.exports = app => {
  if (!db) {
    const config = app.libs.config;
    sequelize = new Sequelize(
      config.database,
      config.username,
      config.password,
      config.params
    );

    db = {
     sequelize,
     Sequelize,
     models: {}
    };

    // Загрузка моделей
    const dir = path.join(__dirname, "models");
    fs.readdirSync(dir).forEach(file => {
      const modelDir = path.join(dir, file);
      const model = sequelize.import(modelDir);
      db.models[model.name] = model;
    });

    Object.keys(db.models).forEach(key => {
      db.models[key].associate(db.models);
    });
  }

  return db;
};

Загрузка моделей происходит при помощи sequelize.import, где в качестве параметра указывается путь к файлу. Для работы с директориями ты работаем с объектом fs при помощи которого получаем список файлов в указанной директории. И в объекте db добавляем эти модели. После этого мы еще раз проходимся по моделям указывая отношение между моделями. Так как мы возвращаем объект db нам стоит немного изменить файл libs/boot.js:

module.exports = app => {
  app.db.sequelize.sync().done(() => {
    app.listen(app.get("port"), () => console.log(`Task API - Port ${app.get("port")}`));
  });
};

Теперь для того, чтобы работать с новыми моделями нужно изменить файл tasks.js в директории routes:

module.exports = app => {
  const Tasks = app.db.models.Tasks;

  app.get("/tasks", (req, res) => {
    Tasks.findAll({}).then(tasks => {
      res.json({tasks: tasks});
    });
  });
};

Откроем страницу по адресу http://localhost:3000/tasks и по итогу мы должны получить:

Ссылка на репозиторий: https://github.com/dikiigr/nodejs-api