これは何?
Sail.jsとMySQLを使ったAPIバックエンドのデモを作ってみたときの手順のメモです。
コード引用箇所は差分だけではなく、コメント文を削除した内容すべてを掲載しています。エラーハンドリングについては完璧ではありませんのでご了承ください。
手順
動作環境
Sails.jsの準備
インストール
npm install -g sails
Step1: DBへの接続をしない構成で動かしてみる
Baseになるプロジェクトを作成する
$ sails new sails_sample
Choose a template for your new Sails app:
1. Web App · Extensible project with auth, login, & password recovery
2. Empty · An empty Sails app, yours to configure
(type "?" for help, or <CTRL+C> to cancel)
HelloコントローラにindexというEndpointを作成する
$ sails generate controller hello index
info: Created a new controller ("hello") at api/controllers/HelloController.js!
Routeを作成する。config/routes.js 以下のように修正する。
$ cat config/routes.js
module.exports.routes = {
'/': { view: 'pages/homepage' },
'GET /api/v1/hello': { controller: 'HelloController', action: 'index' },
};
起動して表示してみる
$ sails inspect
# or
$ sails lift
表示は以下の通り。ブラウザからのアクセスでも同様の出力が得られれば成功。
$ curl http://localhost:1337/api/v1/hello
{
"todo": "index() is not implemented yet!"
}
Step2: DBへの接続をし情報を取得してみる
MySQLの準備
DB,テーブル、ユーザを作成
$ mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.27 Homebrew
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATE DATABASE sails_sample;
Query OK, 1 row affected (0.01 sec)
mysql> CREATE USER sails_sample_user_00@localhost;
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT ALL PRIVILEGES ON sails_sample.* TO sails_sample_user_00@localhost;
Query OK, 0 rows affected (0.01 sec)
mysql> ALTER USER 'sails_sample_user_00'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
Query OK, 0 rows affected (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE sails_sample.table00 (id int auto_increment PRIMARY KEY, message VARCHAR(300));
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO sails_sample.table00 (message) VALUES ('message1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO sails_sample.table00 (message) VALUES ('message2');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO sails_sample.table00 (message) VALUES ('message3');
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> \q
Bye
DBのテーブルの内容を確認する。
$ mysql -u sails_sample_user_00 sails_sample -ppassword
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.27 Homebrew
Copyright (c) 2000, 2021, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SELECT * FROM table00;
+----+----------+
| id | message |
+----+----------+
| 1 | message1 |
| 2 | message2 |
| 3 | message3 |
+----+----------+
3 rows in set (0.00 sec)
Sails.js側での設定
MySQLに接続する為のnpm packageをインストールする。
$ npm install -s sails-mysql
Model全体の設定をする。
$ cat config/models.js
module.exports.models = {
migrate: 'alter',
attributes: {
createdAt: { type: 'number', autoCreatedAt: true },
updatedAt: { type: 'number', autoUpdatedAt: true },
id: { type: 'number', autoIncrement: true, },
dataEncryptionKeys: {
default: 'toJwG8UaxxxxxxxxxxxxxxxxxlhY='
},
cascadeOnDestroy: true
};
DB接続を設定する。
$ cat config/datastores.js
module.exports.datastores = {
default: {
adapter: 'sails-mysql',
url: 'mysql://sails_sample_user_00:password@localhost:3306/sails_sample',
},
};
Modelを生成し、設定する。
$ sails generate model Table00
$ cat Table00.js
module.exports = {
attributes: {
message: 'string',
},
};
Controllerを変更する。
$ cat api/controllers/HelloController.js
module.exports = {
index: async function (req, res) {
Table00.find().exec( function (err, records) {
return res.json(records)
})
}
};
起動して表示してみる
# 起動していたら、Ctrl+cで停止する
$ sails inspect
# or
$ sails lift
表示は以下の通り。ブラウザからのアクセスでも同様の出力が得られれば成功。
$ curl http://localhost:1337/api/v1/hello
[
{
"id": 1,
"message": "message1",
"createdAt": "1634972725856",
"updatedAt": "1634972725856"
},
{
"id": 2,
"message": "message2",
"createdAt": "1634972727834",
"updatedAt": "1634972727834"
},
{
"id": 3,
"message": "message3",
"createdAt": "1634972729549",
"updatedAt": "1634972729549"
}
]
Step3: DBへの接続をし情報投入、更新してみる
情報の投入
投入時のロジックをControllerに追加。
$ cat api/controllers/HelloController.js
module.exports = {
index: async function (req, res) {
Table00.find().exec( function (err, records) {
return res.json(records)
})
},
postMessage: async function (req, res) {
const ret = {
success: false,
message: null,
data: null
}
try {
if ( req.body.message!=null && typeof req.body.message=='string') {
ret.data = await Table00.create({message:req.body.message}).fetch()
ret.success = true
}
console.log(`parm=[${JSON.stringify(ret)}]`)
return res.json(ret)
} catch {
return res.json(ret)
}
},
};
Routeを追加する。
$ cat config/routes.js
module.exports.routes = {
'/': { view: 'pages/homepage' },
'GET /api/v1/hello': { controller: 'HelloController', action: 'index' },
'POST /api/v1/hello/message': { controller: 'HelloController', action: 'postMessage' },
};
再起動してデータを投げてみて、追加されていたら完了。
$ curl -X POST -H "Content-Type: application/json" -d '{"message":"hoge4"}' localhost:1337/api/v1/hello/message
情報を更新
更新時の時のロジックをControllerに追加。
module.exports = {
index: async function (req, res) {
Table00.find().exec( function (err, records) {
return res.json(records)
})
},
postMessage: async function (req, res) {
const ret = {
success: false,
message: null,
data: null
}
try {
if ( req.body.message!=null && typeof req.body.message=='string') {
ret.data = await Table00.create({message:req.body.message}).fetch()
ret.success = true
}
console.log(`parm=[${JSON.stringify(ret)}]`)
return res.json(ret)
} catch {
return res.json(ret)
}
},
patchMessage: async function (req, res) {
const ret = {
success: false,
message: null,
data: null
}
try {
if ( (req.body.id!=null && req.body.message!=null)
&& ( typeof Number(req.body.id)=='number' && typeof req.body.message=='string')
) {
ret.data = await Table00.updateOne({ id: Number(req.body.id) })
.set({ message:req.body.message });
ret.success = true
}
console.log(`parm=[${JSON.stringify(ret)}]`)
return res.json(ret)
} catch {
return res.json(ret)
}
},
};
Routeを追加する。
module.exports.routes = {
'/': { view: 'pages/homepage' },
'GET /api/v1/hello': { controller: 'HelloController', action: 'index' },
'POST /api/v1/hello/message': { controller: 'HelloController', action: 'postMessage' },
'PATCH /api/v1/hello/message': { controller: 'HelloController', action: 'patchMessage' },
};
再起動してデータを投げてみて、更新されていたら完了。
$ curl -X PATCH -H "Content-Type: application/json" -d '{id: 2, "message":"hogehoge2"}' localhost:1337/api/v1/hello/message