Ruby on Rails 5のAPIモードと非APIモードのファイル差分

Ruby on Rails 5からAPIモードが追加されましたが、`rails new` で `--api` を使った場合のファイルの差分が気になったので調べてみました。

下記のコマンドで作成した差分を https://github.com/mh61503891/rails-5-comparison-of-with-api-and-without-api/commit/aa9503e4f7205e402fe133ddd01cb00e2bbb92f8 で公開しています。

```bash
rails new app --api
pushd app
git add *
git commit -m "with --api"
git push
popd
rails new app
pushd app
git add *
git commit -m "without --api"
git push
```

# APIモードにするとどうなるん？

## `Gemfile`

以下のgemsを使わないようです。

* sass-rails
* uglifier
* coffee-rails
* therubyracer
* jquery-rails
* turbolinks
* web-console

UI関連のgemsが省かれています。

ただし、APIモードだけどActionCable (WebSocket) も使いたいよという場合は、サーバサイドのプログラムは多分JavaScriptで書くので `therubyracer` とか、CoffeeScriptを使うなら `coffee-rails` を入れとかなきゃですね。

## `config/application.rb`

非APIモードだと以下のように `rails/all` がrequireされています。

```config/application.rb
require 'rails/all'
```

ちなみに `rails/all`の中身はこんなです。

```.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-5.0.0/lib/rails/all.rb
require 'rails'

%w(
  active_record/railtie
  action_controller/railtie
  action_view/railtie
  action_mailer/railtie
  active_job/railtie
  action_cable/engine
  rails/test_unit/railtie
  sprockets/railtie
).each do |railtie|
  begin
    require railtie
  rescue LoadError
  end
end
```

で、APIモードだと以下のようにAPIモードに必要なライブラリだけ選択的にrequireできるよう個別にrequireするような記述に分割されています。

```config/application.rb
require "rails"		 
# Pick the frameworks you want:		
require "active_model/railtie"		
require "active_job/railtie"		
require "active_record/railtie"		
require "action_controller/railtie"		
require "action_mailer/railtie"		
require "action_view/railtie"		
require "action_cable/engine"		
# require "sprockets/railtie"		
require "rails/test_unit/railtie"
```

まあ、ほぼほぼ、同じようです。（少しだけ並びが違うのが気になるマンが参上して帰って行きました。）

あと以下の設定も追加されています。generatorとかがこれを見て挙動を変えるみたいです。

```config/application.rb
config.api_only = true
```

## `config/environments/*`

以下のファイルからアセットコンパイルとかアセット関連の設定が無くなっています。

* `-+ config/environments/production.rb`
* `-+ config/environments/development.rb`

## `config/initializers/*`

アセットとかクッキーとかセッションストアのイニシャライザがありません。アセットはまあ不要という気がしますが、クッキーとかセッションストアのイニシャライザが無いのはmiddlewareでやりなさいというお告げ？

* `- config/initializers/assets.rb`
* `- config/initializers/cookies_serializer.rb`
* `- config/initializers/session_store.rb`

CSRFとかCross-Origin Resource Sharing (CORS) の設定が、controllerではなくmiddlewareでやるように代わっています。ほほう。

* `- config/initializers/new_framework_defaults.rb`: 非APIモードはここのcontrollerの設定で行う。
* `+ config/initializers/cors.rb`: APIモードはここのmiddlewareで設定を行う。

## `public/*.html`

APIモードにはありません。そらな。

## `app/helpers/*`

APIモードにヘルパーは不要なのでありません。

* `- app/helpers/application_helper.rb`

## `app/views/layouts/*`

ERBとかのビュー関連は無くなっています。

* `- app/views/layouts/application.html.erb`

ただしメール関連のビューはAPIモードでも残っています。

* `app/views/layouts/mailer.html.erb`
* `app/views/layouts/mailer.text.erb`

## `app/assets/*`

アセット関連のディレクトリがありません。javascriptsとかstylesheetsとかはともかく、imagesも無いので、どこに置くのか悩ましいです。APIモードでは画像はpublicかCDNにでも置きなはれというお告げ？

## `app/assets/javascripts/channels/*`

ActionCableのサーバサイドのプログラムを置くディレクトリはAPIモードでもあります。

## `app/controllers/*`

APIモードでのコントローラはActionController::APIを継承する。

```app/controllers/application_controller.rb
class ApplicationController < ActionController::API
end
```