1. naoty_k

    Posted

    naoty_k
Changes in title
+Rails APIモードのdiff
Changes in tags
+Rails
5.0
Changes in body
Source | HTML | Preview
@@ -0,0 +1,266 @@
+既に似たような記事は存在するものの、 initializer や middleware の差分までは触れられていなかったので、捕捉するような記事です。
+
+---
+
+```sh
+$ rails new rails-sample
+$ rails new rails-api-sample --api
+```
+
+* `--api` をつけると API モードで rails アプリケーションを作成する。
+
+```sh
+$ diff -qr rails-sample rails-api-sample
+Files rails-sample/Gemfile and rails-api-sample/Gemfile differ
+Files rails-sample/Gemfile.lock and rails-api-sample/Gemfile.lock differ
+Only in rails-sample/app: assets
+Files rails-sample/app/controllers/application_controller.rb and rails-api-sample/app/controllers/application_controller.rb differ
+Only in rails-sample/app: helpers
+Only in rails-sample/app/views/layouts: application.html.erb
+Files rails-sample/config/application.rb and rails-api-sample/config/application.rb differ
+Files rails-sample/config/environments/development.rb and rails-api-sample/config/environments/development.rb differ
+Files rails-sample/config/environments/production.rb and rails-api-sample/config/environments/production.rb differ
+Only in rails-sample/config/initializers: assets.rb
+Only in rails-sample/config/initializers: cookies_serializer.rb
+Only in rails-api-sample/config/initializers: cors.rb
+Files rails-sample/config/initializers/new_framework_defaults.rb and rails-api-sample/config/initializers/new_framework_defaults.rb differ
+Only in rails-sample/config/initializers: session_store.rb
+Files rails-sample/config/secrets.yml and rails-api-sample/config/secrets.yml differ
+Only in rails-sample/lib: assets
+Only in rails-sample/public: 404.html
+Only in rails-sample/public: 422.html
+Only in rails-sample/public: 500.html
+Only in rails-sample/public: apple-touch-icon-precomposed.png
+Only in rails-sample/public: apple-touch-icon.png
+Only in rails-sample/public: favicon.ico
+Only in rails-sample/test: helpers
+Only in rails-sample/tmp/cache: assets
+Only in rails-sample/vendor: assets
+```
+
+* API モードの Rails アプリケーションには、アセット関連のファイルやディレクトリ、ヘルパー、レイアウトファイル、そして cookie 等の Web ブラウザに関連する設定ファイルがない。
+* 逆に API モードには CORS に関する initializer が存在する。
+
+```
+$ diff {rails-sample,rails-api-sample}/Gemfile
+15,27d14
+< # Use SCSS for stylesheets
+< gem 'sass-rails', '~> 5.0'
+< # Use Uglifier as compressor for JavaScript assets
+< gem 'uglifier', '>= 1.3.0'
+< # Use CoffeeScript for .coffee assets and views
+< gem 'coffee-rails', '~> 4.2'
+< # See https://github.com/rails/execjs#readme for more supported runtimes
+< # gem 'therubyracer', platforms: :ruby
+<
+< # Use jquery as the JavaScript library
+< gem 'jquery-rails'
+< # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
+< gem 'turbolinks', '~> 5'
+29c16
+< gem 'jbuilder', '~> 2.5'
+---
+> # gem 'jbuilder', '~> 2.5'
+37a25,27
+> # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
+> # gem 'rack-cors'
+>
+44,45d33
+< # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
+< gem 'web-console', '>= 3.3.0'
+```
+
+* API モードでは、rack-cors という CORS をケアする rubygems が含まれる。
+* 逆に、API モードでは不要なアセットパイプラインに関わる rubygems は含まれない。
+* API モードでは、jbuilder がコメントアウトされているのが興味深い。JSON 以外のフォーマットが採用される可能性を見越しているのかな。
+
+```sh
+$ diff {rails-sample,rails-api-sample}/app/controllers/application_controller.rb
+1,2c1
+< class ApplicationController < ActionController::Base
+< protect_from_forgery with: :exception
+---
+> class ApplicationController < ActionController::API
+```
+
+* API モードでは CSRF 対策は不要なので削除されている。
+* `ActionController::Base` ではなく `ActionController::API` を継承するようになっている。
+
+```sh
+$ diff {rails-sample,rails-api-sample}/config/application.rb
+3c3,13
+< require 'rails/all'
+---
+> 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"
+9c19
+< module RailsSample
+---
+> module RailsApiSample
+13a24,28
+>
+> # Only loads a smaller set of middleware suitable for API only apps.
+> # Middleware like session, flash, cookies can be added back manually.
+> # Skip views, helpers and assets when generating a new resource.
+> config.api_only = true
+```
+
+* API モードでは `require` する rubygems をひとつひとつ書いている。sprockets は API モードでは不要なのでコメントアウトされている。
+* `require rails/all` の内容と大差はなさそうだが、不要なものをコメントアウトできるようにしてある。
+* API モードでは、generate 時にアセットやヘルパーの generate をスキップするオプションが設定されている。
+
+```sh
+$ diff {rails-sample,rails-api-sample}/config/environments/development.rb
+40,46d39
+< # Debug mode disables concatenation and preprocessing of assets.
+< # This option may cause significant delays in view rendering with a large
+< # number of complex assets.
+< config.assets.debug = true
+<
+< # Suppress logger output for asset requests.
+< config.assets.quiet = true
+$ diff {rails-sample,rails-api-sample}/config/environments/production.rb
+21,28d20
+< # Compress JavaScripts and CSS.
+< config.assets.js_compressor = :uglifier
+< # config.assets.css_compressor = :sass
+<
+< # Do not fallback to assets pipeline if a precompiled asset is missed.
+< config.assets.compile = false
+<
+< # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
+57c49
+< # config.active_job.queue_name_prefix = "rails-sample_#{Rails.env}"
+---
+> # config.active_job.queue_name_prefix = "rails-api-sample_#{Rails.env}"
+```
+
+* 環境設定ファイルはアセットパイプラインの設定の有無が異なっているだけだった。
+
+```sh
+$ diff {rails-sample,rails-api-sample}/config/initializers/new_framework_defaults.rb
+7,12d6
+< # Enable per-form CSRF tokens. Previous versions had false.
+< Rails.application.config.action_controller.per_form_csrf_tokens = true
+<
+< # Enable origin-checking CSRF mitigation. Previous versions had false.
+< Rails.application.config.action_controller.forgery_protection_origin_check = true
+<
+```
+
+* API モードには CSRF 対策は不要ということで、設定が省かれている。
+
+```sh
+$ cd rails-sample
+$ bin/rails initializers > initializers.txt
+$ cd ../rails-api-sample
+$ bin/rails initializers > initializers.txt
+$ cd ..
+$ diff {rails-sample,rails-api-sample}/initializers.txt
+3,5d2
+< set_load_path
+< set_load_path
+< set_load_path
+8,12d4
+< set_autoload_paths
+< set_autoload_paths
+< set_autoload_paths
+< add_routing_paths
+< add_routing_paths
+15,18d6
+< add_routing_paths
+< add_locales
+< add_locales
+< add_locales
+23,28d10
+< add_view_paths
+< add_view_paths
+< add_view_paths
+< load_environment_config
+< load_environment_config
+< load_environment_config
+43a26,29
+> global_id
+> active_job.logger
+> active_job.set_configs
+> active_job.set_reloader_hook
+67,70d52
+< global_id
+< active_job.logger
+< active_job.set_configs
+< active_job.set_reloader_hook
+75,90d56
+< set_default_precompile
+< quiet_assets
+< setup_sass
+< setup_compression
+< jbuilder
+< web_console.initialize
+< web_console.development_only
+< web_console.insert_middleware
+< web_console.mount_point
+< web_console.template_paths
+< web_console.whitelisted_ips
+< web_console.whiny_requests
+< i18n.load_path
+< prepend_helpers_path
+< prepend_helpers_path
+< prepend_helpers_path
+95,98d60
+< load_config_initializers
+< load_config_initializers
+< load_config_initializers
+< engines_blank_point
+100,103d61
+< engines_blank_point
+< engines_blank_point
+< engines_blank_point
+< append_assets_path
+109,114c67
+< append_assets_path
+< override js_template hook
+< append_assets_path
+< append_assets_path
+< turbolinks
+< append_assets_path
+---
+> engines_blank_point
+```
+
+* API モードだと余計な initializers の読み込みが少なくなっているようだ。
+* なお、このコマンドは筆者によって追加されている。
+
+```sh
+$ cd rails-sample
+$ bin/rails middleware > middleware.txt
+$ cd ../rails-api-sample
+$ bin/rails middleware > middleware.txt
+$ cd ..
+$ diff {rails-sample,rails-api-sample}/middleware.txt
+6d5
+< use Rack::MethodOverride
+8d6
+< use Sprockets::Rails::QuietAssets
+11d8
+< use WebConsole::Middleware
+17,19d13
+< use ActionDispatch::Cookies
+< use ActionDispatch::Session::CookieStore
+< use ActionDispatch::Flash
+23c17
+< run RailsSample::Application.routes
+---
+> run RailsApiSample::Application.routes
+```
+
+* `Rack::MethodOverride` とは `params[:_method]` によって HTTP メソッドを上書きするためのミドルウェアで、PUT や DELETE リクエストはこれによって実現している。しかし、これらは フォーム等の HTML が存在しない API モードでは不要なので削除してあると思われる。
+* cookie 等の Web ブラウザに関連するミドルウェアが API モードには含まれない。