Scaffoldは一体何をしているのか?生成されるコードを1行ずつ解説
はじめに
Railsのscaffoldは、開発の初期段階で非常に便利なコマンドです。モデル、ビュー、コントローラなど、Webアプリケーションの基本的な構成要素を自動で生成してくれます。しかし、その便利さゆえに「中で何が起きているかよくわからないまま使っている」という方も多いのではないでしょうか。
この記事では、rails generate scaffoldコマンドが生成するファイルを1つずつ丁寧に読み解き、Railsアプリケーションの仕組みへの理解を深めることを目的とします。
前提
以下のコマンドが実行済みであるとします。
bash
rails generate scaffold Article title:string content:text1. config/routes.rb - ルーティング
scaffoldを実行すると、まずconfig/routes.rbに以下の1行が追加(またはアンコメント)されます。
ruby
# config/routes.rb
Rails.application.routes.draw do
resources :articles
endresources :articles: これは、articlesリソースに対する一連のRESTfulなルートを自動で定義するための記述です。具体的には、以下の7つのアクションに対応するURLとコントローラのアクションがマッピングされます。
| HTTPメソッド | URLパス | コントローラ#アクション | 用途 |
|---|---|---|---|
GET | /articles | articles#index | 全記事の一覧表示 |
GET | /articles/new | articles#new | 新規記事の作成フォーム |
POST | /articles | articles#create | 新規記事の作成処理 |
GET | /articles/:id | articles#show | 特定記事の詳細表示 |
GET | /articles/:id/edit | articles#edit | 特定記事の編集フォーム |
PATCH/PUT | /articles/:id | articles#update | 特定記事の更新処理 |
DELETE | /articles/:id | articles#destroy | 特定記事の削除処理 |
この1行だけで、ブログ記事の基本的な操作に必要なすべてのURLが定義されます。
2. app/controllers/articles_controller.rb - コントローラ
次に、リクエストを処理するコントローラを見てみましょう。
ruby
# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
before_action :set_article, only: %i[ show edit update destroy ]
# GET /articles
def index
@articles = Article.all
end
# GET /articles/1
def show
end
# GET /articles/new
def new
@article = Article.new
end
# GET /articles/1/edit
def edit
end
# POST /articles
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article, notice: "Article was successfully created."
else
render :new, status: :unprocessable_entity
end
end
# PATCH/PUT /articles/1
def update
if @article.update(article_params)
redirect_to @article, notice: "Article was successfully updated."
else
render :edit, status: :unprocessable_entity
end
end
# DELETE /articles/1
def destroy
@article.destroy
redirect_to articles_url, notice: "Article was successfully destroyed."
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
@article = Article.find(params[:id])
end
# Only allow a list of trusted parameters through.
def article_params
params.require(:article).permit(:title, :content)
end
endbefore_action :set_article, ...:show,edit,update,destroyアクションが実行される前に、set_articleメソッドを呼び出す設定です。これにより、各アクションで@article = Article.find(params[:id])という記述を繰り返す必要がなくなります。index:Article.allですべての記事を取得し、インスタンス変数@articlesに格納します。この変数はビュー(index.html.erb)で使われます。show:before_actionで@articleがセットされるので、中身は空です。new: 新しいArticleオブジェクトを作成し、@articleに格納します。これはビューのフォーム (form_with) で使われます。edit:before_actionで@articleがセットされるので、中身は空です。create:newアクションから送信されたパラメータ(article_paramsで安全にフィルタリング済み)を使って新しい記事を作成し、データベースに保存します。保存が成功すれば記事詳細ページにリダイレクトし、失敗すればnewのビューを再表示します。update:editアクションから送信されたパラメータで記事を更新します。成功すれば記事詳細ページにリダイレクトし、失敗すればeditのビューを再表示します。destroy: 記事を削除し、記事一覧ページにリダイレクトします。privateメソッド:set_article: URLの:idパラメータを使って、対象の記事をデータベースから見つけます。article_params: Strong Parametersという仕組みです。フォームから送られてきたデータのうち、titleとcontentだけを許可し、意図しないデータが登録されるのを防ぎます。
3. app/models/article.rb - モデル
モデルファイルは非常にシンプルです。
ruby
# app/models/article.rb
class Article < ApplicationRecord
endclass Article < ApplicationRecord:ArticleクラスがApplicationRecordを継承することを示しています。ApplicationRecordはActiveRecord::Baseを継承しており、これによりArticleモデルはデータベースのarticlesテーブルと連携し、find,all,save,update,destroyなどのメソッドが使えるようになります。
4. app/views/articles/ - ビュー
scaffoldは、各アクションに対応するビューファイルも生成します。
index.html.erb: 記事一覧ページ。@articlesをループして各記事のタイトルを表示し、詳細ページへのリンクを設置します。show.html.erb: 記事詳細ページ。@articleのタイトルと内容を表示します。new.html.erb: 新規作成ページ。_form.html.erbパーシャルを呼び出します。edit.html.erb: 編集ページ。こちらも_form.html.erbパーシャルを呼び出します。_form.html.erb:newとeditで共有されるフォーム部分のテンプレート(パーシャル)です。form_with(model: article)を使い、@articleが新規オブジェクトか既存オブジェクトかを自動で判断して、適切なPOST先(createかupdate)にフォームを送信します。
5. db/migrate/xxxxxxxx_create_articles.rb - マイグレーション
最後に、データベースのテーブル定義です。
ruby
# db/migrate/20240628000000_create_articles.rb (タイムスタンプは実行日時による)
class CreateArticles < ActiveRecord::Migration[7.0]
def change
create_table :articles do |t|
t.string :title
t.text :content
t.timestamps
end
end
endcreate_table :articles:articlesという名前のテーブルを作成します。t.string :title:titleという名前のstring型(文字列)カラムを追加します。t.text :content:contentという名前のtext型(長文テキスト)カラムを追加します。t.timestamps:created_atとupdated_atという2つのタイムスタンプカラムを自動で追加します。これにより、データの作成日時と更新日時が記録されます。
このファイルをもとにrails db:migrateを実行することで、実際にデータベースにテーブルが作成されます。
まとめ
scaffoldは、これらすべてのファイルを連携させて、一つのまとまった機能を一瞬で作り上げてくれます。それぞれのファイルがどのような役割を持ち、どのように連携しているかを理解することで、scaffoldを単なる「魔法のコマンド」から、カスタマイズ可能な「開発の土台」として活用できるようになります。
ぜひ、生成されたコードを自分なりに改造して、Railsアプリケーションの仕組みをより深く探求してみてください。