RailsのAMSとforemanについて学ぶ_100DaysOfCodeチャレンジ15日目(Day_15:#100DaysOfCode)

# はじめに

この記事はTwitterで人気のハッシュタグ`#100DaysOfCode`をつけて、
100日間プログラミング学習を続けるチャレンジに挑戦した15日目の記録です。

## 動作環境

* ruby 2.4.1
* Rails 5.0.1

## 現在学習している内容のリポジトリ

https://github.com/yuta-ushijima/notebook-api-on-rails

## 本日学んだこと

* Foremanについて
* リクエストを受け付けるJSONのフォーマットを指定するメソッドの実装

## Foremanとは？

`rails server`や`npm run dev`のような実行するコマンドが複数ある時に、このgemを入れることで
`foreman start`コマンド一発で同時に実行できる便利なgem。

### 公式リポジトリ

https://github.com/ddollar/foreman

### 製作者のページ

http://blog.daviddollar.org/2011/05/06/introducing-foreman.html

```
# Gemfile
gem 'foreman'
```

railsのルートディレクトリにforemanを起動させるために必要なファイルである`Procfile`を作成しましょう。

作成した`Procfile`に、webサーバーを起動するコマンドを追記します。

```
# Procfile
web: PORT=3000 bundle exec rails s
```

この内容の意味としては、「webサーバーとして、rails serverを使ってね。ポート番号は3000を使うように。」といったところですね。

Foremanではデフォルトのポートが5000になっているので、そのほかのポートを指定したい場合は別途指定が必要なのです。

あとは、foremanコマンドを使うために、システムにもforemanのgemをインストールしましょう。

```
gem install foreman
```

### TIPS

`bundle exec foreman start`のように実行すると、先に記述したポート指定箇所で以下のようなエラーが発生します。

```
Yutas-MacBook-Air:notebook-api-on-rails ushijimayuuta$ bundle exec foreman start
11:21:42 web.1  | started with pid 7745
11:21:42 web.1  | /Users/ushijimayuuta/workspace/Rails/notebook-api-on-rails/vender/bundle/ruby/2.4.0/gems/foreman-0.64.0/bin/foreman-runner: line 41: exec: PORT=3000: not found
11:21:42 web.1  | exited with code 127
11:21:42 system | sending SIGTERM to all processes
```
「bundle execで実行したけど、PORT=3000なんてものはないよ」と怒られているわけですね。

これを解消するために、`-p`オプションを使ってProcfileを以下のように書き換えます。

```
# Procfile
web: bundle exec rails  s -p 3000
```
これでエラーが出ずにforemanを実行することができました。
(「だったら、最初から上記の記述でいいんじゃね？」というツッコミは、なしでお願いします...笑)

ちなみに、gemがシステムのどこにインストールされたか知りたい時は、以下のコマンドを使うと確認できます。

```
gem environment
```

上記のコマンドを実行すると、以下のような情報が返ってきます。`GEM PATH`という項目がありますので、そこが該当箇所ですね。

```
RubyGems Environment:
  - RUBYGEMS VERSION: 2.6.11
  - RUBY VERSION: 2.4.1 (2017-03-22 patchlevel 111) [x86_64-darwin17]
  - INSTALLATION DIRECTORY: /Users/ushijimayuuta/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0
  - USER INSTALLATION DIRECTORY: /Users/ushijimayuuta/.gem/ruby/2.4.0
  - RUBY EXECUTABLE: /Users/ushijimayuuta/.rbenv/versions/2.4.1/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/ushijimayuuta/.rbenv/versions/2.4.1/bin
  - SPEC CACHE DIRECTORY: /Users/ushijimayuuta/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/ushijimayuuta/.rbenv/versions/2.4.1/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-17
  - GEM PATHS:
     - /Users/ushijimayuuta/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0
     - /Users/ushijimayuuta/.gem/ruby/2.4.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /Users/ushijimayuuta/.rbenv/versions/2.4.1/bin
     - /usr/local/Cellar/rbenv/1.1.1/libexec
     - /Users/ushijimayuuta/.rbenv/shims
     - /Users/ushijimayuuta/.rbenv/bin
     - /usr/local/bin
     - /usr/bin
     - /bin
     - /usr/sbin
     - /sbin
     - /sbin
```

## リクエストを受け付けるJSONのフォーマットを指定するメソッドの実装

APIを作成する時に、どのようなリクエストなら受け付けるかを指定できると、よりセキュリティを高めることができます。

今回は`application_controller.rb`に受け付けるJSONのフォーマットを制御する`ensure_json_request`メソッドをの学習しました。

```
# application_controller.rb

class ApplicationController < ActionController::API
  before_action :ensure_json_request

  def ensure_json_request
    return if request.headers["Accept"] =~ /vnd\.api\+json/
    render :head, status: 406
  end
end

```

メソッドの中身を説明しておきましょう。

`before_action`により、APIの各アクションが実行される前に、まずこの`ensure_json_request`が実行されるようになります。

中身の説明としては、まず`ensure_json_request`が呼ばれると、1行目による条件分岐が走りますね。

request.headerにより、リクエストヘッダーの"Accept"を取得し、`=~`で正規表現を使って右辺である`/vnd\.api\+json/`と比較。

それがtrueであればreturnされます。

そうじゃない場合は、ステータスコードの406(Not acceptable)を返すという処理ですね。

これによってAcceptに`application/vnd.api+json`、つまりJSONのフォーマットの一つであるJSON　API以外が指定された場合は、リクエストを受け付けなくなります。

　## まとめ

Active_Model_SerializerでMediaTypeを使うことで、リクエストのレスポンス形式を指定できるということですね。

## 参考リンク

https://wa3.i-3-i.info/word15786.html