1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Sails.js + MySQLでAPIバックエンドを作ってみる。

Last updated at Posted at 2021-10-23

これは何?

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

Reference

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?