【Rails】APIとシンプルな管理画面を提供する最小構成のプロジェクト作成
概要
APIとシンプルな管理画面を提供する最小構成のRailsプロジェクト作成について記述します。
最小には、Railsアプリケーションのスリム化と外部依存性を抑制する意図があります。
- APIと管理画面を同一のRailsプロジェクトから提供します。
- APIはcontrollerからjson/msgpackをrenderし、viewは使用しません。
- 管理画面はviewでHTMLを出力します。
- 管理画面のcss/jsはbootstrapなどの静的なファイルを用いる前提で、アセットパイプラインは使用しません。
- デフォルトでインストールされるaction-mailer,active-storage,action-cableなどは使用しません。(requireしません。)
デフォルトのRailsプロジェクトはAPIサーバには多機能でAPIモードにしたいけど、管理画面ではHTMLを使いたいと思い、簡易な実装で試してみました。
環境
- Apple M2 Pro
- macOS 13.5.2(Ventura)
- Ruby 3.2.2
- Rails 7.0.8
プロジェクト作成
以下のコマンドでプロジェクトを作成しました。
APIモードで各種のインストールをスキップします。
rails new projectname \
--database=mysql \
--skip-action-mailer \
--skip-action-mailbox \
--skip-action-text \
--skip-active-job \
--skip-active-storage \
--skip-action-cable \
--skip-asset-pipeline \
--skip-javascript \
--skip-hotwire \
--skip-jbuilder \
--api
rails newのヘルプで各オプションの概要を確認できます。
rails new -h
Rails newのドキュメントはこちら。
Railsドキュメント
apiオプション
--api
オプションを指定することで、APIモードでRailsプロジェクトが作成されます。
APIモードの特徴は以下の通りです。
- html,css,jsなどview関連のgemがインストールされません。
- 使用するミドルウェアが絞り込まれます。
- Controllerの基底クラスが
ActionController::Base
からActionController::API
に変更されます。
apiオプションの詳細はこちら。
Railsガイド
minimalオプション
--api
オプションとは別に最小構成でインストールを行う--minimal
というオプションがあります。
以下のコマンドで冒頭に記載したプロジェクトと近しい構成になりましたが、Railsの起動を高速化するbootsnap
が含まれませんでした。
rails new projectname --database=mysql --api --minimal
--no-skip-bootsnap
を指定しても、--minimal
が優先され、bootsnap
は含まれませんでした。
rails new projectname --database=mysql --api --minimal --no-skip-bootsnap
bootsnap
の有無による差分は以下の2点だったので、プロジェクトを作成した後でも追加しやすいです。
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
require "bootsnap/setup" # Speed up boot time by caching expensive operations.
APIモードでHTMLを出力するためにやったこと
APIモードでプロジェクトを作成した場合、そのままではviewを使用してHTMLを出力できません。
また、cookieやsessionも利用できません。
管理画面を開発するにあたり、以下の対応を行いました。
Controllerの基底クラスを変更した
APIと管理画面でControllerの基底クラスを分け、管理画面のControllerはActionController::Base
を継承しました。
これによりviewを使用してHTMLを出力できるようになりました。
module Admin
class ControllerBase < ActionController::Base
layout 'admin'
end
end
使用するmiddlewareを明示的に指定した
画面からの入力にform、処理結果の表示にflashを使用するため、以下のmiddlewareを明示的に使用しました。
管理画面の利用者が限定的なので、セッション管理にCookieStore
を使用しました。
ブラウザにセッション情報を保存する形ですが、セキュリティを強化する場合は、memcachedやredisでセッションを管理し、サーバーサイドに寄せることも可能です。
# 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
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
デフォルトのRailsプロジェクトと比較し、APIモードで利用されなかったmiddlewareは以下の通りです。
- Rack::MethodOverride
- Sprockets::Rails::QuietAssets
- WebConsole::Middleware
- ActionDispatch::Cookies
- ActionDispatch::Session::CookieStore
- ActionDispatch::Flash
- ActionDispatch::ContentSecurityPolicy::Middleware
- ActionDispatch::PermissionsPolicy::Middleware
- Rack::TempfileReaper
静的なcss/jsを使用した
アセットパイプラインのインストールをスキップしているので、静的なcss/jsを使用します。
bootstrapあたりをlayoutsに含めておけば、フロントエンドが苦手でもそれっぽい感じの管理画面をさくっと作れます。
public
├── javascripts
│ └── bootstrap.min.js
├── robots.txt
└── stylesheets
└── bootstrap.min.css
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : 'Admin Tool' %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'bootstrap.min' %>
<%= yield :head %>
</head>
<body>
...
<%= javascript_include_tag 'bootstrap.min' %>
</body>
</html>
おわりに
APIモードでそれっぽい画面を出力することができました。
めでたしめでたし。
Discussion