すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 Scaffolding機能の使い方を初心者向けにわかりやすく解説

ぴっかちゃん
ぴっかちゃん

Scaffolding機能とは、アプリケーションに必要となる基本的な操作(CRUD)を実現するために必要なファイルをまとめて生成してくれる機能のことです。

例えば、Scaffolding機能(rails g scaffold)を使うことで次のように「作成・読み込み・更新・削除することができるユーザの管理画面」を簡単に実装することができます。

ユーザ管理画面

基本機能を実装したアプリケーションをすぐ実装することができれば、gemなど何か機能を試したいときに便利です。

ぜひScaffolding機能の使い方や自動生成されるファイルなどを把握しておきましょう。

scaffoldとは

この章ではscaffoldの使い方だけではなく、どんなファイルが自動生成されるのかまで学べる内容になっているので「コマンドは何回か実行したことがあるが、正直何をしているのかよく分からない」という方におすすめです。

使い方

Scaffolding機能は、次のようにrails generateコマンドを使用します。

ターミナル | 基本構文
1
rails generate scaffold モデル名 [カラム名:型]

例えば、次の画像にあるusersテーブルを作成する場合を考えてみましょう。

usersテーブルの中身

この場合は、次のコードのようにusersテーブルを操作するUserモデルとテーブルに必要なカラムと型をそれぞれ指定します。

ターミナル | usersテーブルを操作する場合
1
2
rails generate scaffold User name:string age:integer
#rails generate scaffold モデル名 カラム名:型 カラム名:型

nameカラムに格納するデータは文字列なのでstringの型、ageカラムには年齢を整数で格納したいのでintegerの型を指定します。

指定することができるカラムの型は、次の表のとおりです。

カラムの型 説明
string 文字列
text 長い文字列
integer 整数
float 浮動小数
decimal 精度の高い小数
datetime 日時
time 時間
date 日付
binary バイナリデータ
boolean Boolean

参考:https://railsdoc.com/page/rails_scaffold

自動生成ファイル

Scaffolding機能を使用すると、次の動画のようにたくさんのファイルが自動生成されます。

scaffoldを実行した場合

自動生成されるファイルは、以下の基本的な操作(CRUD)を実現するために必要なファイルになります。

  • 一覧(index)
  • 詳細(show)
  • 新規作成(new/create)
  • 編集(edit/update)
  • 削除(destroy)

今回は、次のコマンドを実行したので「ユーザ一覧、ユーザー詳細、ユーザの新規作成、ユーザの編集、ユーザの削除」に必要なファイルが生成されることになります。

ターミナル | ユーザのCRUD操作に必要なファイルを生成する
1
rails generate scaffold User name:string age:integer

それでは、自動生成される主要なファイルを確認していきましょう。

ルーティング

ルーティングは、自動生成されるファイルというわけではありませんが、次のようにresources :usersが追加されます。

config/routes.rb | 自動で設定されるルーティングの内容
1
2
3
Rails.application.routes.draw do
resources :users # Usersコントローラの7つのアクションにルートが設定される
end

上記のresourcesメソッドによって、7つのルーティングが自動で設定されます。

次のようにrails routesで確認すると、Usersコントローラの7つのアクションに割り当てられていることがわかりますね。

ターミナル | rails routesでルーティングを確認する
1
2
3
4
5
6
7
8
9
10
Prefix    Verb   URI Pattern                  Controller#Action

users     GET    /users(.:format)             users#index
          POST   /users(.:format)             users#create
new_user  GET    /users/new(.:format)         users#new
edit_user GET    /users/:id/edit(.:format)    users#edit
user      GET    /users/:id(.:format)         users#show
          PATCH  /users/:id(.:format)         users#update
          PUT    /users/:id(.:format)         users#update
          DELETE /users/:id(.:format)         users#destroy

ちなみに次の実行箇所でルーティングにresources :usersは追加されます。

scaffoldを実行した場合のルーティング設定

このようにscaffoldを実行すると、CRUD操作に必要なルーティングが自動で設定されます。

ポイント
  1. resourcesで7つのルーティングが自動で設定される
  2. ルーティングファイルを自動生成するわけではない

コントローラ

コントローラは、次の箇所によってusers_controller.rbが自動生成されます。

scaffoldのコントローラファイルの実行結果

自動生成されるコントローラファイルは、次のようにapp/controllers/配下に置かれます。

コントローラファイルの構造

users_controller.rbの中身は、次のようにユーザ一覧、ユーザ詳細、ユーザの新規作成、ユーザの編集、ユーザの削除に必要なソースコードが記述されます。

app/controllers/users_controller.rb | 自動生成されるコントローラファイルの中身
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class UsersController < ApplicationController
  before_action :set_user, only: %i[ show edit update destroy ]

  # GET /users or /users.json
  def index
    @users = User.all
  end

  # GET /users/1 or /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users or /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: "User was successfully created." }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1 or /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: "User was successfully updated." }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1 or /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: "User was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def user_params
      params.require(:user).permit(:name, :age)
    end
end

コントローラに定義される各アクションの目的は、次の表の通りです。

アクション 目的 利用するメソッド等
index すべてのユーザの一覧を表示する allメソッド
show 特定のユーザを表示する before_action
findメソッド
params
new ユーザを1つ作成するためのHTMLフォームを返す newメソッド
edit ユーザ編集用のHTMLフォームを1つ返す before_action
findメソッド
params
create ユーザを1つ作成する createメソッド
saveメソッド
respond_to
redirect_to
renderメソッド
ストロングパラメータ
update 特定のユーザを更新する before_action
findメソッド
params
ストロングパラメータ
destroy 特定のユーザを削除する before_action
findメソッド
params
destroyメソッドrespond_to
redirect_to
ポイント
  1. コントローラファイルは、app/controllers/配下に置かれる
  2. コントローラファイルの中身もCRUD操作に必要なソースコードが記述される

モデル

モデルは、app/models/配下にデータベースのテーブル操作のためのファイルが自動生成されます。

今回は、次のようにUserモデルのクラスが定義されているuser.rbが生成されます。
この定義によってusersテーブルを操作することができます。

app/models/user.rb | usersテーブルを操作するためのUserモデル
1
2
class User < ApplicationRecord
end

また、次のようにusersテーブルを作成するために必要なマイグレーションファイルも自動生成されます。マイグレーションファイルには、rails g scaffoldで指定したカラム名と型が反映されます。

db/migrate/20210408100759_create_users.rb | usersテーブルの設計図
1
2
3
4
5
6
7
8
9
10
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name
      t.integer :age

      t.timestamps
    end
  end
end

データベース作成済みの場合は「rails db:migrate」を実行することで、次のようにデータベースに反映することができます。(※手順はScaffolding機能を使ってみようで解説しています。)

usersテーブル

次の箇所でテーブルの設計図であるマイグレーションファイルとテーブル操作に必要なモデルクラスのファイルが生成されることがわかりますね。

モデルのscaffoldの実行結果

このようにscaffoldを実行すると、テーブルの作成と操作に必要なファイルが自動生成されます。

ポイント
  1. モデルファイルとマイグレーションファイルが自動で生成される
  2. モデルファイルは、テーブルを操作するために必要になファイル
  3. マイグレーションファイルは、テーブルの設計図の役割を持つ

ビュー

ビューは、app/views配下に管理画面を表示するためのファイルが自動生成されます。

今回は、次のようにapp/views/users/配下にユーザ操作に必要な管理画面のファイルが生成されます。

ユーザ操作に必要な管理画面

自動生成される主要なビューファイルは、次の表のとおりです。

主要なファイル 説明
_form.html.erb 新規投稿/編集画面の共通フォーム
index.html.erb 一覧画面
edit.html.erb 編集画面
new.html.erb 新規登録画面
show.html.erb 詳細画面

次の箇所でerbのビューファイルが生成されます。

erbのscaffoldの実行結果

それでは、実際に表示される画面とファイルのソースコードを合わせてみていきましょう。

index.html(一覧画面)

index.htmlは、次のようにユーザ一覧画面を表示します。

一覧画面

上記の一覧画面を表示するファイルの中身は、次のとおりです。

app/views/users/index.html.erb | ユーザ一覧画面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<p id="notice"><%= notice %></p>

<h1>Users</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.age %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table> <br> <%= link_to 'New User', new_user_path %>

ハイライトされる箇所に注目してください。
全てのユーザ情報が格納されるインスタンス変数(@users)からeachメソッドで1つ1つ取り出すことで各ユーザの情報を表示することができています。

また、link_toメソッドでユーザ一覧画面から詳細/編集/削除/新規投稿の画面に遷移できるようにしています。

一覧画面の遷移箇所

このようにユーザ一覧画面は、登録したユーザ情報の確認とリンクから4つの画面に遷移することができます。

ポイント
  1. index.htmlは、一覧画面を表示するビューファイル
  2. インスタンス変数(@users)には、全てのユーザ情報が格納される
  3. 一覧画面から各画面に遷移することができる
edit.html.erb(編集画面)

edit.html.erbは、次のようにユーザ編集画面を表示します。

編集画面

緑枠で囲っている箇所は、新規投稿/編集画面の共通フォームである_form.html.erbを呼び出して表示させています。

編集画面を表示するファイル(edit.html.erb)の中身は、次のとおりです。

app/views/users/edit.html.erb | ユーザ編集画面
1
2
3
4
5
6
<h1>Editing User</h1>

<%= render 'form', user: @user %><!-- _form.html.erbを呼び出す -->
<%= link_to 'Show', @user %> | <%= link_to 'Back', users_path %>

renderメソッドで先ほどの緑枠で囲った_form.html.erb(部分テンプレート)を呼び出しています。上記のハイライト箇所は、「省略した書き方」で記述されてます。

呼び出し先のファイル(_form.html.erb)の中身は、次のとおりです。

app/views/users/_form.html.erb | 共通フォーム
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<%= form_with(model: user, local: true) do |form| %>
  <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div class="field">
    <%= form.label :age %>
    <%= form.number_field :age %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

_form.html.erbuserには、edit.html.erbで渡された@user(特定のユーザの情報)が格納されます。

そして、次のコードのようにuserを「form_withの引数」に渡して処理を行います。

app/views/users/_form.html.erb | 共通フォーム
1
2
3
4
5
6
<%# @user(特定のユーザ情報)が格納されたuserをformに渡す%>
<%= form_with(model: user, local: true) do |form| %>
<%= form.text_field :name %><%# 他省略 %> <%= form.number_field :age %> <%= form.submit %> <% end %>

このように特定のユーザ情報があるので、次のようにユーザの名前と年齢が表示されます。

_form.html.erbにユーザ情報を渡す流れ

インスタンス変数(@user)に特定のユーザ情報が格納される場合、form_withのコンパイル後は、次のようにupdateアクションが動くパスに変換されます。

HTML | form_withをコンパイルした場合
1
2
<form action="/users/編集するレコードのid" method="post" data-remote="true">
  <input type="hidden" name="_method" value="patch"><!--他省略-->

そのため、編集画面では選択したユーザ情報を編集して送信ボタンを押すことで、更新処理をリクエストすることができるのです。

ポイント
  1. edit.html.erbは、編集画面を表示するビューファイル
  2. 内部では部分テンプレート(_form.html.erb)を呼び出している
  3. インスタンス変数(@user)には、特定のユーザの情報が格納される
new.html.erb(新規登録画面)

new.html.erbは、次のようにユーザの新規登録画面を表示します。

新規登録画面

新規登録画面でも編集画面と同様に_form.html.erbを呼び出して入力フォームを表示しています。

app/views/users/new.html.erb | ユーザの新規登録画面
1
2
3
4
5
<h1>New User</h1>

<%= render 'form', user: @user %><!-- _form.html.erbを呼び出す -->
<%= link_to 'Back', users_path %>

しかし新規登録画面と編集画面のファイルには大きな違いが1点あります。
それは、@userに格納されているのは特定のユーザ情報ではなく、次のように新しく生成されたUserのインスタンスだということです。

app/controllers/users_controller.rb | @userの中身を確認する
1
2
3
4
5
class UsersController < ApplicationController
  def new
    @user = User.new #Userインスタンスを生成して@userへ
  end
end

上記の@userは新規登録画面のフォームの初期値を与えるために必要になります。

app/views/users/_form.html.erb | 共通フォーム
1
2
3
4
5
6
<%# @user(新しく生成されたUserインスタンス)が格納されたuserをformに渡す%>
<%= form_with(model: user, local: true) do |form| %>
<%= form.text_field :name %><%# 他省略 %> <%= form.number_field :age %> <%= form.submit %> <% end %>

@userに特定のユーザ情報がない場合は、次のようにform_withがコンパイルされると、createアクションが動くパスに変換されます。

HTML | form_withのコンパイル後
1
<form action="/users" method="post" data-remote="true">

そのため新規登録画面で入力された内容は更新ではなく、新規登録されることになります。

ポイント
  1. new.html.erbは、新規登録画面を表示するビューファイル
  2. インスタンス変数(@user)には、新しく生成されたUserのインスタンスが格納される
  3. インスタンス変数(@user)は、フォームの初期値に必要である
show.html.erb(詳細画面)

show.html.erbは、次のように特定ユーザの詳細画面を表示します。

特定ユーザの詳細画面

詳細画面を表示するファイル(show.html.erb)の中身は、次のとおりです。

app/views/users/show.html.erb | 特定ユーザの詳細画面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
<%= @user.name %>
</p> <p> <strong>Age:</strong>
<%= @user.age %>
</p>
<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

上記の@userには、以下の編集画面と同様に特定のユーザ情報が格納されています。

app/views/users/edit.html.erb | ユーザ編集画面
1
2
3
4
5
6
<h1>Editing User</h1>

<%= render 'form', user: @user %><!-- _form.html.erbを呼び出す -->

<%= link_to 'Show', @user %> |
<%= link_to 'Back', users_path %>
ポイント
  1. show.html.erbは、詳細画面を表示するビューファイル
  2. インスタンス変数(@user)には、特定のユーザの情報が格納される
jbuilderファイル

erb以外にもjbuilderのビューファイルも自動生成されます。

jsonのscaffoldの実行結果

これらのファイルは、非同期通信JSON形式のデータを返すときによく使用します。

主要なファイル 説明
_user.json.jbuilder 共通スクリプト
index.json.jbuilder ユーザの一覧情報をJSON形式で返す
show.json.jbuilder 特定のユーザ情報をJSON形式で返す

その他のファイル

ここまで紹介した主要ファイル以外に生成されるファイルは、次の表のとおりです。

その他の自動生成ファイル(Rails5.2.5) 説明
test/models/user_test.rb モデル用テストファイル
test/fixtures/users.yml fixtureファイル
test/controllers/users_controller_test.rb コントローラ用テストファイル
test/system/users_test.rb システムテストファイル
app/helpers/users_helper.rb ヘルパー
app/assets/javascripts/users.coffee モデル固有のCoffeeScript
app/assets/stylesheets/users.scss モデル固有のSCSSスタイルシート
app/assets/stylesheets/scaffolds.scss デフォルトのスタイルシート

各ファイルの使い方や自動テストの作り方は、こちらの参考書で学ぶことができます。

自動生成ファイルのまとめ
  1. scaffoldを実行すると、一覧(index)・詳細(show)・新規作成(new/create)・編集(edit/update)・削除(destroy)するために必要なコントローラ、モデル、ビューファイルがまとめて自動生成される
  2. ルーティングファイルには、上記の操作に必要な7つのルーティングが自動設定される
  3. その他にも関連するテストファイルやヘルパーなど自動生成される

オプション

scaffoldは、オプションを使用することができます。

ターミナル | 基本構文(オプションを使用する場合)
1
rails generate scaffold モデル名 [カラム名:型] オプション

例えば、デフォルトで自動生成されるjbuilderのビューファイルがいらない場合は、次のように--skip-jbuilderを指定して実行します。

ターミナル | ヘルパーファイルを生成させない場合
1
rails generate scaffold User name:string age:integer --skip-jbuilder

次の画像のように--skip-jbuilderを指定した場合は、jbuilderファイルが生成されないことがわかりますね。

skipオプションは、自動生成されるファイルを必要な分だけに絞ることができるので便利ですね。

他にも便利なオプションがたくさんありますが、次の表では主要なオプションだけ紹介させていただきます。

主要なオプション 説明
–-skip-ファイル名 指定したファイルを自動生成させない
–-skip-bundle bundle installを行わない
–-database=DATABASE データベースの種類を指定する
-f, –force ファイルが存在する場合に上書きする

メリット・デメリット

Scaffolding機能のメリットは、一通りのCRUD機能があるサンプルアプリケーションを簡単に作ることができるところです。gemなど何か機能を試したいときにとても便利です。

しかし、初心者の方がMVCなどRailsの基本的な仕組みを理解しなくても簡単にCRUD機能があるアプリケーションを作れてしまうというデメリットも存在します。

初心者の方は、なるべくScaffolding機能を使わないでルーティング定義、コントローラ・モデル作成など1つ1つ作りながら仕組みを理解していきましょう。

そして、慣れてきて何か機能を試したいときにScaffolding機能でサンプルアプリケーションを作ってみましょう。

実際にScaffolding機能を使ってみよう

それでは実際にサンプルアプリケーションを作成し、ユーザ管理するためのCRUD機能をScaffolding機能を使って実装していきます。

まずは、rails newでサンプルアプリケーションを作成します。
ターミナルで次のコマンドを実行してください。

ターミナル | sample_appという名前のアプリケーションを作成する
1
rails _5.2.1_ new sample_app -d mysql # Rails5.2.1、DBはmysqlを指定

次に、Scaffolding機能を使ってユーザ管理するためのCRUD機能を実装します。
次のコマンドを実行してください。

ターミナル | ディレクトリを移動しコマンドを実行する
1
2
3
cd sample_app # ディレクトリを移動する
rails g scaffold User name:string age:integer # scaffoldを実行
# rails g scaffold モデル名 カラム名:型 カラム名:型

上記のコマンドを実行すると、次の動画のようにたくさんのファイルが生成されますが処理が止まるまで少し待ってください。

scaffoldを実行した場合

そして、データベースの作成と自動生成されたマイグレーションファイルをデータベースに反映させるため、次のコマンドを実行します。

ターミナル(sample_appの階層) | データベース作成とマイグレーション実行
1
bundle exec rails db:create && bundle exec rails db:migrate

最後にrails serverでサーバーを起動させてlocalhost:3000/usersにアクセスすると、次のようにユーザーの登録・表示・編集の機能を使用することができます。

ユーザ管理画面

これで簡易的なユーザ管理画面を実装することができました。

実際に作成してみていかがでしたか。コマンドを数回実行するだけで実装できたので、とても簡単でしたね。

アプリケーションの土台は作成することができたので、ぜひ「gem一覧」から何か興味ある機能を選んで実装してみてください。

この記事のまとめ

  • Scaffolding機能を使えば、アプリケーションにCRUD機能を簡単に実装できる
  • CRUD機能とは、データ作成(Create)/読み込み(Read)/更新(Update)/削除(Delete)の基本的な機能のこと
  • Railsの基本的な仕組みを理解した上で使うようにしよう!