はじめに
この記事はTwitterで人気のハッシュタグ#100DaysOfCode
をつけて、
100日間プログラミング学習を続けるチャレンジに挑戦した15日目の記録です。
動作環境
- ruby 2.4.1
- Rails 5.0.1
現在学習している内容のリポジトリ
本日学んだこと
- Foremanについて
- リクエストを受け付けるJSONのフォーマットを指定するメソッドの実装
Foremanとは?
rails server
やnpm run dev
のような実行するコマンドが複数ある時に、このgemを入れることで
foreman start
コマンド一発で同時に実行できる便利なgem。
公式リポジトリ
製作者のページ
# 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を使うことで、リクエストのレスポンス形式を指定できるということですね。