Rails5,MySQLの開発環境構築を行う

## 目的
Ruby on Rails5でREST APIを作成する。
その為にRuby on Rails + MySQLが動作する環境をローカルに作成する。

## 環境
以下の環境で行う。

- Mac OS X El Capitan 10.11.6
- Virtualbox 5.0.26
- Vagrant 1.8.5

MacOS上にVagrantを使ってVirtualboxを立てその中に環境構築を行っていく。
OSイメージはCentOS7系の[こちら](https://atlas.hashicorp.com/centos/boxes/7) を利用する。

## OSの基本設定
以下の設定を行っていく。

- タイムゾーンの設定
- ロケールの設定
- SELinux無効化
- ファイアウォールの停止
- ファイアウォール自動起動解除

これらの作業は以前投稿させて頂いた、[LAMP 環境構築 PHP 7 MySQL 5.7（前編）](http://qiita.com/keita-nishimoto/items/5441244604fbc6db7907) と内容的に同様なので詳しい手順はこちらを参照。

## 各種コマンドのインストール（お好みで）

こちらも[LAMP 環境構築 PHP 7 MySQL 5.7（前編）](http://qiita.com/keita-nishimoto/items/5441244604fbc6db7907) と内容的に同様なので詳しい手順はこちらを参照。

他はともかくgitだけは後の手順で利用するので必ずインストールしておく。

## Rubyのインストール
[rbenvを使ってSinatraの実行環境を整えるまで](http://qiita.com/keita-nishimoto/items/8a89a176943a44adbebb) をに手順が記載してあるので参照。

上記記事と異なる点が2点あるので下記に記載しておく。

- Rubyのバージョンは最新安定版の2.3.1を利用
- openssl、openssl-devel、readline-develを依存パッケージとして入れているが、今回利用したCentOS7では下記の3つを入れる事で動作確認が出来た。
    - openssl-devel
    - readline-devel
    - zlib-devel

## MySQLのインストール
今回Railsから利用するDBサーバはMySQLを利用する。
5.7系の最新安定版を利用。

インストールの詳しい手順については、[LAMP 環境構築 PHP 7 MySQL 5.7（後編）](http://qiita.com/keita-nishimoto/items/7d0a8d6e24c1861d799f) に記載してある。

## DBとユーザーの作成
成果物となるアプリケーションで利用するDBとユーザーを作成する。
テストコードで利用する物と合わせてそれぞれ作成を行う。
テスト用なので名前は適当で。私は下記の名前で作成を行った。

| DB | User |
|:-:|:-:|
| rails5_api  | rails5_api_user  |
| rails5_api_test  | rails5_api_test_user  |

※上記の例と同じにするなら、MySQLサーバにrootでログインして以下を実行する。

```mysql:ユーザー作成
GRANT ALL ON rails5_api.* TO `rails5_api_user`@`localhost` IDENTIFIED BY '任意なパスワード';
GRANT ALL ON rails5_api_test.* TO `rails5_api_test_user`@`localhost` IDENTIFIED BY '任意なパスワード';
```

## Railsのインストール

vagrantユーザーのホームディレクトリで作業を進める。
プロジェクトルートとなるディレクトリを作成しそこに移動する。

```
$ mkdir rails5-api-prototype
$ cd rails5-api-prototype
```

以下のコマンドでGemfileを作成する。

```bash:Gemfileの作成
$ bundle init
```

Gemfileに以下の行を追加する。 

```ruby:Gemfile
gem 'rails', '5.0.0.1'
```

```bash:インストール
$ bundle install --path vendor/bundle
```

少々時間がかかるがここまででRailsのインストールは完了。

## Railsプロジェクトの作成

先程と同じくプロジェクトルートで以下のコマンドを実行する。

```bash:APIモードでプロジェクトを作成する
$ bundle exec rails new . --api -d mysql
```

※ "--api"がAPIプロジェクトを作成する為のオプション。

## テスト用のエンドポイントを作成する

Railsにはコードを自動生成する「scaffold」という仕組みが備わっている。
今回はこれを利用しusersというエンドポイントを作成し動作確認を行う。

```bash:プロジェクトルートで実行
$ bundle exec rails g scaffold users
```

しばらく時間がかかるが成功するといくつかのファイルが自動生成される。

## DB名、DBユーザー名の変更

config/database.yml というファイルを編集する。
この記事の「DBとユーザーの作成」に合わせて修正を行う。

※パスワードの部分は各自設定したパスワードに合わせて欲しい。
私の場合は"Rails@RootPassword999@"を設定した。
無論これはローカルのテスト環境だからである、本番環境では十分に強固なパスワードを設定する事を推奨する。

```yaml:config/database.yml
# MySQL. Versions 5.0 and up are supported.
#
# Install the MySQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem 'mysql2'
#
# And be sure to use new-style password hashing:
#   http://dev.mysql.com/doc/refman/5.7/en/old-client.html
#
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: rails5_api_user
  password: Rails@RootPassword999@
  socket: /var/lib/mysql/mysql.sock

development:
  <<: *default
  database: rails5_api

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: rails5_api_test

# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
#   DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
#   production:
#     url: <%= ENV['DATABASE_URL'] %>
#
production:
  <<: *default
  database: rails5_api
  username: rails5_api_user
  password: <%= ENV['RAILS5-API-PROTOTYPE_DATABASE_PASSWORD'] %>
```

## マイグレーションの実行

先程のscaffoldでマイグレーションファイルが作成されているハズなので下記のコマンドを実行する。
※マイグレーションとはざっくり言うとDBのテーブル定義等をプログラム（この場合はRubyのコード）で管理する仕組みである。

```bash:マイグレーションの実行
$ bundle exec rails db:migrate
```

しばらく時間がかかるが成功すると、DB内に以下のテーブルが作成されているハズだ。

```sql:usersテーブル
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
```

## アプリケーションの起動、動作確認

```bash:アプリケーションの起動
bundle exec rails s -b 0.0.0.0
```

しばらくするとターミナルに以下のように表示されアプリケーションが起動する。

```
=> Booting Puma
=> Rails 5.0.0.1 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options

Puma starting in single mode...
* Version 3.6.0 (ruby 2.3.1-p112), codename: Sleepy Sunday Serenity
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

POSTメソッドでリクエストを送信しリソースを1件作成してみよう。

```bash:userリソースを1件作成
$ curl -kv -X POST http://192.168.33.50:3000/users
```

```http:レスポンス
POST /users HTTP/1.1
Host: 192.168.33.50:3000
User-Agent: curl/7.43.0
Accept: */*

HTTP/1.1 201 Created
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Location: http://192.168.33.50:3000/users/1
Content-Type: application/json; charset=utf-8
ETag: W/"5809a1c71c0d7af395ba2f3a36f98c08"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: f0a8d732-7dc1-453e-bb3d-df7288300cfa
X-Runtime: 0.043142
Transfer-Encoding: chunked

* Connection #0 to host 192.168.33.50 left intact
{"id":1,"created_at":"2016-10-22T13:07:05.000Z","updated_at":"2016-10-22T13:07:05.000Z"}
```

1件リソースが作成された。
次は作成されたリソースを取得する。

```bash:先程作成したリソースを取得する
curl -kv http://192.168.33.50:3000/users/1
```

```http:レスポンス
GET /users/1 HTTP/1.1
Host: 192.168.33.50:3000
User-Agent: curl/7.43.0
Accept: */*

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf-8
ETag: W/"5809a1c71c0d7af395ba2f3a36f98c08"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 05e46e81-c9ec-496c-83e3-5e68ee66a32c
X-Runtime: 3.066195
Transfer-Encoding: chunked

* Connection #0 to host 192.168.33.50 left intact
{"id":1,"created_at":"2016-10-22T13:07:05.000Z","updated_at":"2016-10-22T13:07:05.000Z"}
```

DBにもちゃんと登録されている事が確認出来るかと思う。

```sql:DBの中身を確認
mysql> SELECT * FROM users WHERE id = 1;
+----+---------------------+---------------------+
| id | created_at          | updated_at          |
+----+---------------------+---------------------+
|  1 | 2016-10-22 13:07:05 | 2016-10-22 13:07:05 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)
```

## まとめ

ここまでで、Rails5のAPIモードを動作確認出来た。
ここまでの内容は以下のGitRepositoryに登録してある。

- [rails5-api-prototype](https://github.com/keita-nishimoto/rails5-api-prototype)
    - 本投稿で作成したプログラム
- [rails5-vagrant](https://github.com/keita-nishimoto/rails5-vagrant)
    - プログラムを動作させる為のVagrantfile
- [rails5-ansible](https://github.com/keita-nishimoto/rails5-ansible)
    - 各ミドルウェアのインストール手順をまとめた[Ansible](https://www.ansible.com/)のplaybook

## 参考記事
以下の記事を参考にさせて頂きました。

- [Rails 5 (api mode) セットアップメモ](http://qiita.com/qsona/items/0459b55de5164452d85f)