Sails.js v1.2.2 を触ってみる（インストール 〜 Hello, world まで）

# はじめに

会社で node を使った開発を検討している（するとは言っていない）ので、個人的に気になったフレームワーク **sails.js** を触ってみました。

sails は名前からわかるとおり、Rails にインスピレーションを受けて作られたとのことで、Rails を使ったことがある方なら特に扱いやすいのではないかと思います。

本記事では、sails をインストールしてからブラウザに Hello, World! を表示させるまでを試してみたいと思います！ :ship:

# 環境

OS: macOS High Sierra 10.13.6
node.js: 10.15.1
Sials.js: 1.2.2

# インストール

npm を使って一発インストール。

```
$ npm install -g sails
```

# プロジェクトの作成

以下のコマンドで sails のプロジェクトを作成します。

```
$ 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)
? 1
```

これで sails のプロジェクトが作成されました。
簡単ですね。

# Hello, world! を表示させる

次は Hello, world! をブラウザに表示させてみましょう。

## コントローラの作成

まずはコントローラを作成しましょう。
先ほど作ったプロジェクトファイルに移動して、次のコマンドを実行します。

```
$ sails new controller hello index
```

すると、`api/controllers` の中に `HelloController` が作成されます。
アクション名を指定したので、コントローラ内に初めから index アクションが作られています。

中身を見てみましょう。

```api/controllers/HelloController.js
module.exports = {

  /**
   * `HelloController.index()`
   */
  index: async function (req, res) {
    return res.json({
      todo: 'index() is not implemented yet!'
    });
  }

};
```

なお、アクションは以下のように複数指定することもできるみたいです。

```
$ sails new controller hello index show etc
```

## ルーティングの設定

ルーティングは `config/` フォルダ内の `routes.js` で設定します。
次の１行を追記します。

```config/routes.js
'GET /hello': { controller: 'HelloController', action: 'index' },
```

これで `/hello` にアクセスしたとき、先ほど作った HelloController の index アクションが呼ばれます。

きちんと設定できているか試してみましょう。
ターミナルで以下のコマンドを実行してサーバーを起動します。

```
$ sails inspect
```

`sails lift` でもサーバーが起動できますが、inspect で起動するとデバッグができるので、開発段階ではこっちで起動した方が便利かも？

```
debug: Running v0 bootstrap script...  (looks like this is the first time the bootstrap has run on this computer)
 info: 
 info:                .-..-.
 info: 
 info:    Sails              <|    .-..-.
 info:    v1.2.2              |\
 info:                       /|.\
 info:                      / || \
 info:                    ,'  |'  \
 info:                 .-'.-==|/_--'
 info:                 `--'-------' 
 info:    __---___--___---___--___---___--___
 info:  ____---___--___---___--___---___--___-__
 info: 
 info: Server lifted in `/Users/user/projects/sails_sample`
 info: To shut down Sails, press <CTRL> + C at any time.
 info: Read more at https://sailsjs.com/support.

debug: -------------------------------------------------------
debug: :: Fri Jun 14 2019 13:27:15 GMT+0900 (GMT+09:00)

debug: Environment : development
debug: Port        : 1337
debug: -------------------------------------------------------
```

無事、出航できました。

この状態で `localhost:1337` にアクセスすると...

![スクリーンショット 2019-06-14 13.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238891/2a94fee9-80d3-9684-965c-8a5ce053d09f.png)

こんな感じの画面が表示されます。
次に `localhost:1337/hello` へアクセスしてみます。
（おそらくログインを促されると思うので、画面右上の Sing up から適当にアカウントを作成してログインしてください。）

画面には以下のような json が表示されるかと思います。

```
{
  "todo": "index() is not implemented yet!"
}
```

「なにも実装されてねーぞ！」ということなので、実装していきましょう。

# ビューの作成

簡単なビューを用意しましょう。
`views/` フォルダ内に `hello` というフォルダを作り、さらにその中に `index.ejs` を作ります。

```views/hello/index.ejs
<h1>Hello, <%- name %>!</h1>
```

コントローラから渡された変数 name を表示できるようにしておきます。

# コントローラの編集

先ほど作った `HelloController` を編集しましょう。
json ではなくビューを返すようにします。

```api/controllers/HelloController.js

module.exports = {

  /**
   * `HelloController.index()`
   */
  index: async function (req, res) {
    return res.view('hello/index', {
      name: 'world', // 引数 name をビューへ渡す
    });
  }

};

```

ここで返すビューファイル（index.ejs）が、コントローラと同じ名前のフォルダ（hello）の中にあり、かつアクションと同じ名前（index）である場合、`res.view('path', {...})` の `path` 部分を省略できます。

```api/controllers/HelloController.js
module.exports = {

  /**
   * `HelloController.index()`
   */
  index: async function (req, res) {
    return res.view({ // ビューファイルへのパスを省略
      name: 'world',
    });
  }

};
```

それでは想定どおりビューが表示されるかを確認します。

`contrl + c` で一度サーバーを落とし、再度 `sails inspect` を実行します。
サーバーが起動できたら `http://localhost:1337/hello` へアクセス。
（おそらくここでもログインを求められます。）

ここで `Hello, world!` と表示されれば成功です！

また、`HelloController` 内で定義した `name: 'world'` を `name: '世界'` に変えれば、ブラウザ上の表示も `Hello, 世界！` に変わるはずですので試してみてください。

# ポリシーの変更

少しおまけです。
`http://localhost:1337/hello` へアクセスするたびにログインを求められるのは、ポリシーの設定によるものです。
何度もログインするのは少々めんどくさいので、ポリシーを変更しましょう。

`config/policies.js` を編集します。

```config/policies.js
module.exports.policies = {

  '*': 'is-logged-in',

  // Bypass the `is-logged-in` policy for:
  'entrance/*': true,
  'account/logout': true,
  'view-homepage-or-redirect': true,
  'view-faq': true,
  'view-contact': true,
  'legal/view-terms': true,
  'legal/view-privacy': true,
  'deliver-contact-form-message': true,

  // 以下を追記
  HelloController: {
    'index': true,
  },

};
```

これで、`http://localhost:1337/hello` へアクセスしてもログインを求められないようになりました。


 - `'*': 'is-logged-in'`： すべてのアクションに対してログインが必要（この `is-logged-in` というルールは `api/policies/is-logged-in.js` というファイル内で定義されています）。
 - `'action': true`： ここで指定したアクションはログインに関係なくアクセス可能。

とりあえず今回はこのくらいで！