Quantcast
Viewing all articles
Browse latest Browse all 8902

[JS1日クッキング]SequelizeとExpressでAPIサーバー

何かを簡単に作って、ちょっとした勉強になる。そんなシリーズになる予定です。

今回は、Node.jsで簡単なTodoアプリに使うAPIサーバーを作っていきます。データベースはMySQLで、データベース操作にはSequelizeを利用します。

完成品はこちら -> sequelize-todo-api-server

材料

  • mysql2
  • sequelize
  • sequelize-cli
  • express

作り方

1. ライブラリのインストール

適当にディテクトリ作って、npm initで初期化してから、今回使うライブラリをインストールします。

npm i sequelize mysql2
npm i -D sequelize-cli

予めMySQLサーバーをインストールして、設定をしておきます。以下は今回使うユーザー名とパスワードです。

usemysql;createusersequelize@localhostidentifiedby'password';mysql>grantallon*.*tosequelize@localhost;exit;

2. データベースを作る

データベースがMySQLかPostgreSQLの場合は、sequelize-cliでコマンドを打っていくことで簡単にデータベースのマイグレーションや初期値のセットなどができます。

sequelize-cli initを利用して、Sequelizeの初期化をします。

npx sequelize-cli init

Sequelize CLI [Node: 14.2.0, CLI: 5.5.1, ORM: 5.21.10]

Created "config/config.json"
Successfully created models folder at "/home/kei/Programming/Project/temp/sequelize-test/models".
Successfully created migrations folder at "/home/kei/Programming/Project/temp/sequelize-test/migrations".
Successfully created seeders folder at "/home/kei/Programming/Project/temp/sequelize-test/seeders".

初期化をすると、3つのディレクトリが作成されます。config/config.jsonの設定をしていきます。自動生成されたconfig.jsonのusernameとpasswordの部分を実際のデータベースで設定したユーザー名とパスワードにします。operatorsAliasesの項目があるとエラーになるので、ある場合は削除します。

config/config.json
{"development":{"username":"sequelize","password":"password","database":"database_development","host":"127.0.0.1","dialect":"mysql"},"test":{"username":"sequelize","password":"password","database":"database_test","host":"127.0.0.1","dialect":"mysql"},"production":{"username":"sequelize","password":"password","database":"database_production","host":"127.0.0.1","dialect":"mysql"}}

下のコマンドでデータベースを作ります。

$ npx sequelize-cli db:create

Sequelize CLI [Node: 14.2.0, CLI: 5.5.1, ORM: 5.21.10]

Loaded configuration file "config/config.json".
Using environment "development".
Database database_development created.

config.jsonのdevelopmantの設定に従って、データベースが作成されました。

3. モデルとテーブルの作成

npx sequelize-cli model:generateでモデルを作成し、npx sequelize-cli db:migrateでデータベースのテーブルを作成します。

$ npx sequelize-cli model:generate --name Todo --attributes title:string,completed:boolean

Sequelize CLI [Node: 14.2.0, CLI: 5.5.1, ORM: 5.21.10]

New model was created at /home/kei/Programming/Project/temp/sequelize-test/models/todo.js .
New migration was created at /home/kei/Programming/Project/temp/sequelize-test/migrations/20200521050853-Todo.js .$ npx sequelize-cli db:migrate

Sequelize CLI [Node: 14.2.0, CLI: 5.5.1, ORM: 5.21.10]

Loaded configuration file "config/config.json".
Using environment "development".== 20200521050853-create-todo: migrating ========= 20200521050853-create-todo: migrated (0.087s)
mysql>usedatabase_development;Databasechangedmysql>showtables;+--------------------------------+|Tables_in_database_development|+--------------------------------+|SequelizeMeta||Todos|+--------------------------------+2rowsinset(0.00sec)mysql>select*fromTodos;Emptyset(0.00sec)

4. テスト用の初期値の準備

テスト用の初期値を作成します。Seederを利用すると、コマンドで初期値をセットしたり、破棄したりできるようになります。

npx sequelize-cli seed:generateでSeederを用意します。

$ npx sequelize-cli seed:generate --name test-data

Sequelize CLI [Node: 14.2.0, CLI: 5.5.1, ORM: 5.21.10]

seeders folder at "/home/kei/Programming/Project/temp/sequelize-test/seeders" already exists.
New seed was created at /home/kei/Programming/Project/temp/sequelize-test/seeders/20200521060543-test-data.js .

このコマンドで作成されたファイルに、初期値を書いていきます。

seeders/20200521060543-test-data.js
"use strict";module.exports={up:(queryInterface,Sequelize)=>{consttodos=[{title:"草むしり",completed:false,updatedAt:newDate(2020,4,22,9,47,19),createdAt:newDate(2020,4,22,9,47,19),},{title:"買い物",completed:true,updatedAt:newDate(2020,4,20,18,2,33),createdAt:newDate(2020,4,20,15,41,58),},{title:"トイレ掃除",completed:false,updatedAt:newDate(2020,4,20,18,4,21),createdAt:newDate(2020,4,20,18,4,21),},];returnqueryInterface.bulkInsert("Todos",todos);},down:(queryInterface,Sequelize)=>{returnqueryInterface.bulkDelete("Todos",null,{});},};

npx sequelize db:seed:allでテーブルに初期値を書き込みます。

$ npx sequelize db:seed:all

Sequelize CLI [Node: 14.2.0, CLI: 5.5.1, ORM: 5.21.10]

Loaded configuration file "config/config.json".
Using environment "test".== 20200521060543-test-data: migrating ========= 20200521060543-test-data: migrated (0.049s)
mysql>usedatabase_development;Databasechangedmysql>select*fromTodos;+----+-----------------+-----------+---------------------+---------------------+|id|title|completed|createdAt|updatedAt|+----+-----------------+-----------+---------------------+---------------------+|1|草むしり|0|2020-05-2200:47:19|2020-05-2200:47:19||2|買い物|1|2020-05-2006:41:58|2020-05-2009:02:33||3|トイレ掃除|0|2020-05-2009:04:21|2020-05-2009:04:21|+----+-----------------+-----------+---------------------+---------------------+3rowsinset(0.00sec)

5. データ処理する関数を書く

とりあえず、CRUD処理をするため、

  • create: 1つのアイテムを書き込む
  • read: すべてのアイテムを取得
  • update: 1つのアイテムを更新する
  • deleteItem: 1つのアイテムを削除する

という4つの関数を書きます。updateとdeleteItemはidで対象アイテムを指定します。

lib/db-simple.js
const{Todo}=require("../models");constcreate=async(title,completed)=>{consttodo=awaitTodo.create({title,completed});returntodo.dataValues;};constread=async()=>{consttodos=awaitTodo.findAll();returntodos.map((todo)=>todo.dataValues);};constupdated=async(id,title,completed)=>{constisUpdate=awaitTodo.update({title,completed},{where:{id,},});returnisUpdated[0]?{message:"updated"}:{error:"item not found"};};constdeleteItem=async(id)=>{constisDeleted=awaitTodo.destroy({where:{id,},});returnisDeleted?{message:"deleted"}:{error:"item not found"};};module.exports={create,read,update,deleteItem};

update関数のisUpdatedはアップデートした件数が配列の1番目に入っています。なので、それでアップデートしたかを判定しています。deleteItem関数のisDeletedも同様です。

6. サーバーを作る

Expressでサーバーを作ります。先ほど作った関数とURLを結びつけるだけです。

index-simple.js
constexpress=require("express");constdb=require("./lib/db-simple");constapp=express();app.use(express.json());app.use(express.urlencoded({extended:true}));app.get("/",async(req,res)=>{consttodos=awaitdb.read();res.json(todos);});app.post("/create",async(req,res)=>{constresult=awaitdb.create(req.body.title,req.body.completed);res.json(result);});app.put("/update",async(req,res)=>{constresult=awaitdb.update(req.body.id,req.body.title,req.body.completed);res.json(result);});app.delete("/delete",async(req,res)=>{constresult=awaitdb.deleteItem(req.body.id);res.json(result);});app.listen(3000,()=>console.log("listening on port 3000"));

下はPostmanで"/"にget、"/create"にpostしたときの結果です。

Image may be NSFW.
Clik here to view.
postman-get.png

Image may be NSFW.
Clik here to view.
postman-post.png

おわりに

Sequelizeは、慣れればDjangoのORMとほぼ同じように使えるような気がします。とても便利です。

これ書いた人は色々調べながら+実は少しテストも書きながら+記事書きながら作っていたので、作成日数が1日を超えました\(^o^)/

コード -> sequelize-todo-api-server


Viewing all articles
Browse latest Browse all 8902

Trending Articles