Rails scaffoldについて
はじめに
YouTubeでRailsの基本について復習してたら知らなかったことが出てきたのでメモっときます📝
やっぱり色々なところから知識をいいとこ取りしていくのがいいね🌱
scaffoldとは
CRUD(クラッド)機能をコマンド一発で簡単に作れる!!!
Create = 新規追加
Read = 一覧、詳細
Update = 編集
Delete = 削除
⇩
CRUDとは、データ作成(Create)/読み込み(Read)/更新(Update)/削除(Delete)の基本的な機能のこと!
使い方
rails generate scaffold モデル名 [カラム名:型]
例えば、今回は体重管理システムを作りたいので、下記のコマンドを実行する!
rails g scaffold WeightHistroy user:references weight:integer memo:string
reference型を指定したカラム名は テーブル名_id となる。
(user:references なので、 user_id というカラムが生成される)
(referencesを指定したことで、生成されたモデルファイルにbelongs_to :userも追加される。)
weightは体重を整数で格納したいので、integer
型、memoには文字列string
を指定!
🏋🏻指定することができるカラムの型一覧🏋🏻
カラムの型 | 説明 |
---|---|
string | 文字列 |
text | 長い文字列 |
integer | 整数 |
float | 浮動小数 |
decimal | 精度の高い小数 |
datetime | 日時 |
time | 時間 |
date | 日付 |
binary | バイナリデータ |
boolean | Boolean |
自動生成ファイル
Scaffolding機能を使用すると、こんな感じでたくさんのファイルが自動で生成される!
(基本的な操作(CRUD)を実現するために必要なファイルたち)
- 一覧(index)
- 詳細(show)
- 新規作成(new/create)
- 編集(edit/update)
- 削除(destroy)
今回は次のコマンドを実行したので、体重の一覧、体重の詳細、体重の新規作成、体重の編集、体重の削除に必要なファイルが作成された!
rails g scaffold WeightHistroy user:references weight:integer memo:string
ルーティング
ルーティングは、自動生成されるファイルというわけではないが、resources :weight_histroys
が追加される!
Rails.application.routes.draw do
resources :weight_histroys
end
上記のresourcesメソッドによって、7つのルーティングが自動で設定される。
(rails routes | grep <文字列>
で絞って表示できます!)
ちなみに、resourcesで特定のアクションだけを指定したい時は、、
onlyとexcept
(indexとshowを指定したい場合だと)
resources :weight_histroys, only: [:index, :snow]
もしくは下記のように記述しても同じ!
resources :weight_histroys, except: [:new, :create, :edit, :update, :destroy]
どちらを使っても構わないが、
only
を使ったほうが使用するアクションを明示的にできるので可読性が上がる!
特定のアクションしか使用しない場合はこのようにonly
やexcept
を使った方がスッキリする。
※ルーティングがスッキリするだけでonly
やexcept
を絶対に使わなければいけないわけではない。
コントローラ
自動生成されるコントローラファイルは、次のようにapp/controllers/配下に置かれる。
weight_histroys_controllerの中には、体重の一覧、体重の詳細、体重の新規作成、体重の編集、体重の削除に必要なソースコードが記述される!
weight_histroys_controller.rbの中身
class WeightHistroysController < ApplicationController
before_action :set_weight_histroy, only: %i[ show edit update destroy ]
# GET /weight_histroys or /weight_histroys.json
def index
@weight_histroys = WeightHistroy.all
end
# GET /weight_histroys/1 or /weight_histroys/1.json
def show
end
# GET /weight_histroys/new
def new
@weight_histroy = WeightHistroy.new
end
# GET /weight_histroys/1/edit
def edit
end
# POST /weight_histroys or /weight_histroys.json
def create
@weight_histroy = WeightHistroy.new(weight_histroy_params)
respond_to do |format|
if @weight_histroy.save
format.html { redirect_to weight_histroy_url(@weight_histroy), notice: "Weight histroy was successfully created." }
format.json { render :show, status: :created, location: @weight_histroy }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @weight_histroy.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /weight_histroys/1 or /weight_histroys/1.json
def update
respond_to do |format|
if @weight_histroy.update(weight_histroy_params)
format.html { redirect_to weight_histroy_url(@weight_histroy), notice: "Weight histroy was successfully updated." }
format.json { render :show, status: :ok, location: @weight_histroy }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @weight_histroy.errors, status: :unprocessable_entity }
end
end
end
# DELETE /weight_histroys/1 or /weight_histroys/1.json
def destroy
@weight_histroy.destroy
respond_to do |format|
format.html { redirect_to weight_histroys_url, notice: "Weight histroy was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_weight_histroy
@weight_histroy = WeightHistroy.find(params[:id])
end
# Only allow a list of trusted parameters through.
def weight_histroy_params
params.require(:weight_histroy).permit(:user_id, :weight, :memo)
end
end
respond_toメソッド
create,update,destroyアクションには、リクエストされるフォーマットがJSON形式の場合も記述されているので、不要であれば削除しちゃってOK!
モデル
app/models/配下にデータベースのテーブル操作のためのファイルが自動生成される。
この定義によってweight_historyテーブルを操作することができる。
class WeightHistroy < ApplicationRecord
belongs_to :user
end
(最初の作成時にreferencesを指定したことで、生成されたモデルファイルにbelongs_to :userも追加されてます!)
(Userモデル側には何も定義されていないので自分で記述する!)
必要なマイグレーションファイルも自動生成されています!
rails g scaffoldで指定したカラム名と型が反映される。
class CreateWeightHistroys < ActiveRecord::Migration[7.0]
def change
create_table :weight_histroys do |t|
t.references :user
t.integer :weight
t.string :memo
t.timestamps
end
end
end
データベース作成済みの場合はrails db:migrate
で、データベースに反映させる。
ビュー
app/views配下に管理画面を表示するためのファイルが自動生成される。
部分テンプレートまで作成してくれてる、、!
自動生成される主要なビューファイル一覧
主要なファイル | 説明 |
---|---|
_form.html.erb | 新規投稿/編集画面の共通フォーム |
index.html.erb | 一覧画面 |
edit.html.erb | 編集画面 |
new.html.erb | 新規登録画面 |
show.html.erb | 詳細画面 |
index.html(一覧画面)
index.htmlは、次のようにUser,Weight,Memoの一覧を表します。
(Userは元々user_idが表示されてましたが変更済みの画面です。)
index.html.erbの中身
<p style="color: green"><%= notice %></p>
<h1>Weight histroys</h1>
<div id="weight_histroys">
<% @weight_histroys.each do |weight_histroy| %>
<%= render weight_histroy %>
<p>
<%= link_to "Show this weight histroy", weight_histroy %>
</p>
<% end %>
</div>
<%= link_to "New weight histroy", new_weight_histroy_path %>
edit.html.erb(編集画面)
edit.html.erbは、次のように編集画面を表示します。
(edit.html.erb)の中身
<h1>Editing weight histroy</h1>
<%= render "form", weight_histroy: @weight_histroy %>
<br>
<div>
<%= link_to "Show this weight histroy", @weight_histroy %> |
<%= link_to "Back to weight histroys", weight_histroys_path %>
</div>
呼び出し先の(_form.html.erb)の中身(部分テンプレート)
エラーメッセージの表示の記述まで入ってます!⚠️
<%= form_with(model: weight_histroy) do |form| %>
<% if weight_histroy.errors.any? %>
<div style="color: red">
<h2><%= pluralize(weight_histroy.errors.count, "error") %> prohibited this weight_histroy from being saved:</h2>
<ul>
<% weight_histroy.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div>
<%= form.label :user_id, style: "display: block" %>
<%= form.text_field :user_id %>
</div>
<div>
<%= form.label :weight, style: "display: block" %>
<%= form.number_field :weight %>
</div>
<div>
<%= form.label :memo, style: "display: block" %>
<%= form.text_field :memo %>
</div>
<div>
<%= form.submit %>
</div>
<% end %>
⇩
インスタンス変数(@user)に特定のユーザ情報が格納される場合、form_withのコンパイル後は、次のようにupdateアクションが動くパスに変換される。
<form action="/weight_historys/編集するレコードのid" method="post" data-remote="true">
<input type="hidden" name="_method" value="patch"><!--他省略-->
そのため、編集画面では選択したユーザ情報を編集して送信ボタンを押すことで、更新処理をリクエストすることができる!
(ここの仕組みよく分かってなかった!!)
new.html.erb(新規登録画面)
new.html.erbは、次のようにユーザの新規登録画面を表示する。
(new.html.erb)の中身
<h1>New weight histroy</h1>
<%= render "form", weight_histroy: @weight_histroy %>
<br>
<div>
<%= link_to "Back to weight histroys", weight_histroys_path %>
</div>
新規登録画面でも編集画面と同様に_form.html.erbを呼び出して入力フォームを表示している!
が、@userに格納されているのは特定のユーザ情報ではなく、新しく生成されたUserのインスタンスのこと。
class UsersController < ApplicationController
def new
@user = User.new #Userインスタンスを生成して@userへ
end
end
@userは新規登録画面のフォームの初期値を与えるために必要になる!
⇩
@userに特定のユーザ情報がない場合は、次のようにform_withがコンパイルされると、createアクションが動くパスに変換される。
<form action="/weight_historys" method="post" data-remote="true">
そのため新規登録画面で入力された内容は更新ではなく、新規登録されることになる!!
show.html.erb(詳細画面)
show.html.erbは、次のように特定の詳細画面を表示する。
( show.html.erb)の中身
<p style="color: green"><%= notice %></p>
<%= render @weight_histroy %>
<div>
<%= link_to "Edit this weight histroy", edit_weight_histroy_path(@weight_histroy) %> |
<%= link_to "Back to weight histroys", weight_histroys_path %>
<%= button_to "Destroy this weight histroy", @weight_histroy, method: :delete %>
</div>
jbuilderファイル
erb以外にもjbuilderのビューファイルも自動生成されており、
これらのファイルは、非同期通信でJSON形式のデータを返すときによく使用される。
その他にも関連するテストファイルやヘルパーなど自動生成されている!
オプション
scaffoldは、オプションを使用することができる🙆🏻♀️
rails generate scaffold モデル名 [カラム名:型] オプション
例えば、デフォルトで自動生成されるjbuilderのビューファイルがいらない場合は、次のように--skip-jbuilderを指定して実行すると、jbuilderファイルが生成されない!!
便利!!
rails generate scaffold User name:string age:integer --skip-jbuilder
主要なオプション一覧(他にもたくさんあるらしい!)
主要なオプション | 説明 |
---|---|
–-skip-ファイル名 | 指定したファイルを自動生成させない |
–-skip-bundle | bundle installを行わない |
–-database=DATABASE | データベースの種類を指定する |
-f, –force | ファイルが存在する場合に上書きする |
こんなに楽に作れるのね、、!!
だから初心者はなるべくScaffolding機能を使わず、仕組みを理解してからの方がいいってことか〜〜🧐
これやりながら新しい発見もたくさんあって大満足です。
おやすみなさい〜〜🌙
🌱参考にさせていただいた記事
Discussion