更新日:
【Rails】 Scaffolding機能の使い方を初心者向けにわかりやすく解説
Scaffolding機能とは、アプリケーションに必要となる基本的な操作(CRUD)を実現するために必要なファイルをまとめて生成してくれる機能のことです。
例えば、Scaffolding機能(rails g scaffold
)を使うことで次のように「作成・読み込み・更新・削除することができるユーザの管理画面」を簡単に実装することができます。
基本機能を実装したアプリケーションをすぐ実装することができれば、gemなど何か機能を試したいときに便利です。
ぜひScaffolding機能の使い方や自動生成されるファイルなどを把握しておきましょう。
scaffoldとは
この章ではscaffold
の使い方だけではなく、どんなファイルが自動生成されるのかまで学べる内容になっているので「コマンドは何回か実行したことがあるが、正直何をしているのかよく分からない」という方におすすめです。
使い方
Scaffolding機能は、次のようにrails generate
コマンドを使用します。
1
rails generate scaffold モデル名 [カラム名:型]
例えば、次の画像にあるusers
テーブルを作成する場合を考えてみましょう。
この場合は、次のコードのようにusers
テーブルを操作するUser
モデルとテーブルに必要なカラムと型をそれぞれ指定します。
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機能を使用すると、次の動画のようにたくさんのファイルが自動生成されます。
自動生成されるファイルは、以下の基本的な操作(CRUD)を実現するために必要なファイルになります。
- 一覧(index)
- 詳細(show)
- 新規作成(new/create)
- 編集(edit/update)
- 削除(destroy)
今回は、次のコマンドを実行したので「ユーザ一覧、ユーザー詳細、ユーザの新規作成、ユーザの編集、ユーザの削除」に必要なファイルが生成されることになります。
1
rails generate scaffold User name:string age:integer
それでは、自動生成される主要なファイルを確認していきましょう。
ルーティング
ルーティングは、自動生成されるファイルというわけではありませんが、次のようにresources :users
が追加されます。
1
2
3
Rails.application.routes.draw do
resources :users # Usersコントローラの7つのアクションにルートが設定される
end
上記のresourcesメソッドによって、7つのルーティングが自動で設定されます。
次のようにrails routesで確認すると、Usersコントローラの7つのアクションに割り当てられていることがわかりますね。
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を実行すると、CRUD操作に必要なルーティングが自動で設定されます。
コントローラ
コントローラは、次の箇所によって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 |
モデル
モデルは、app/models/
配下にデータベースのテーブル操作のためのファイルが自動生成されます。
今回は、次のようにUserモデルのクラスが定義されているuser.rb
が生成されます。
この定義によってusers
テーブルを操作することができます。
1
2
class User < ApplicationRecord
end
また、次のようにusersテーブルを作成するために必要なマイグレーションファイルも自動生成されます。マイグレーションファイルには、rails g scaffold
で指定したカラム名と型が反映されます。
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機能を使ってみようで解説しています。)
次の箇所でテーブルの設計図であるマイグレーションファイルとテーブル操作に必要なモデルクラスのファイルが生成されることがわかりますね。
このようにscaffoldを実行すると、テーブルの作成と操作に必要なファイルが自動生成されます。
ビュー
ビューは、app/views
配下に管理画面を表示するためのファイルが自動生成されます。
今回は、次のようにapp/views/users/
配下にユーザ操作に必要な管理画面のファイルが生成されます。
自動生成される主要なビューファイルは、次の表のとおりです。
主要なファイル | 説明 |
---|---|
_form.html.erb | 新規投稿/編集画面の共通フォーム |
index.html.erb | 一覧画面 |
edit.html.erb | 編集画面 |
new.html.erb | 新規登録画面 |
show.html.erb | 詳細画面 |
次の箇所でerbのビューファイルが生成されます。
それでは、実際に表示される画面とファイルのソースコードを合わせてみていきましょう。
index.html(一覧画面)
index.html
は、次のようにユーザ一覧画面を表示します。
上記の一覧画面を表示するファイルの中身は、次のとおりです。
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つの画面に遷移することができます。
edit.html.erb(編集画面)
edit.html.erb
は、次のようにユーザ編集画面を表示します。
緑枠で囲っている箇所は、新規投稿/編集画面の共通フォームである_form.html.erb
を呼び出して表示させています。
編集画面を表示するファイル(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
)の中身は、次のとおりです。
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.erb
のuser
には、edit.html.erb
で渡された@user(特定のユーザの情報)が格納されます。
そして、次のコードのようにuser
を「form_withの引数」に渡して処理を行います。
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 %>
このように特定のユーザ情報があるので、次のようにユーザの名前と年齢が表示されます。
インスタンス変数(@user
)に特定のユーザ情報が格納される場合、form_withのコンパイル後は、次のようにupdateアクションが動くパスに変換されます。
1
2
<form action="/users/編集するレコードのid" method="post" data-remote="true">
<input type="hidden" name="_method" value="patch"><!--他省略-->
そのため、編集画面では選択したユーザ情報を編集して送信ボタンを押すことで、更新処理をリクエストすることができるのです。
new.html.erb(新規登録画面)
new.html.erb
は、次のようにユーザの新規登録画面を表示します。
新規登録画面でも編集画面と同様に_form.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のインスタンスだということです。
1
2
3
4
5
class UsersController < ApplicationController
def new
@user = User.new #Userインスタンスを生成して@userへ
end
end
上記の@user
は新規登録画面のフォームの初期値を与えるために必要になります。
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アクションが動くパスに変換されます。
1
<form action="/users" method="post" data-remote="true">
そのため新規登録画面で入力された内容は更新ではなく、新規登録されることになります。
show.html.erb(詳細画面)
show.html.erb
は、次のように特定ユーザの詳細画面を表示します。
詳細画面を表示するファイル(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
には、以下の編集画面と同様に特定のユーザ情報が格納されています。
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 %>
jbuilderファイル
erb以外にもjbuilderのビューファイルも自動生成されます。
これらのファイルは、非同期通信で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 | デフォルトのスタイルシート |
各ファイルの使い方や自動テストの作り方は、こちらの参考書で学ぶことができます。
オプション
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でサンプルアプリケーションを作成します。
ターミナルで次のコマンドを実行してください。
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 モデル名 カラム名:型 カラム名:型
上記のコマンドを実行すると、次の動画のようにたくさんのファイルが生成されますが処理が止まるまで少し待ってください。
そして、データベースの作成と自動生成されたマイグレーションファイルをデータベースに反映させるため、次のコマンドを実行します。
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の基本的な仕組みを理解した上で使うようにしよう!