
第1章:CRUDって何?

プロ太先生、CRUDって何ですか?クラッド?

CRUDは、4つの英単語の頭文字を取ったものなんだよ。
- Create(作成)- 新しいデータを作る
- Read(読み取り)- データを見る・表示する
- Update(更新)- 既存のデータを変更する
- Delete(削除)- データを消す

なるほど!つまり、データの基本的な操作ってことですね。

その通り!例えば、君がSNSに投稿するとき…
・新しい投稿を書く(Create)
・投稿を見る(Read)
・投稿を編集する(Update)
・投稿を削除する(Delete)
これ全部CRUDなんだ!
第2章:Railsでの準備 – コントローラーの基本

じゃあ、実際にRailsで商品(Product)を管理するシステムを作ってみよう。まずは基本のコントローラーから見てみよう。
class ProductsController < ApplicationController
# 商品一覧を表示するアクション
def index
@products = Product.all # 全ての商品をデータベースから取得
end
# 個別の商品を表示するアクション
def show
@product = Product.find(params[:id]) # IDを使って特定の商品を取得
end
end

@products
と@product
って何で@マークが付いてるんですか?

いい質問だね!@マークが付いた変数は「インスタンス変数」と呼ばれて、コントローラーからビュー(画面)に値を渡すための特別な変数なんだ。
覚え方:@マーク = アット(at)= そこにある つまり、画面でも使えるようにそこに置いておく変数だと思えばいいよ!
第3章:Create(作成)- 新しい商品を作ろう

じゃあ、実際に新しい商品を作る機能を追加してみよう!
3-1. newアクション(フォームを表示)
class ProductsController < ApplicationController
def index
@products = Product.all # 全商品を表示用に取得
end
def show
@product = Product.find(params[:id]) # 指定された商品を取得
end
def new
@product = Product.new # 新しい空の商品オブジェクトを作成
end
end

Product.new
って何ですか?

これは「まっさらな商品の箱」を用意するイメージだよ。まだ中身は何も入っていないけど、これからユーザーが情報を入力するための準備をしているんだ。
3-2. フォームを作る(new.html.erb)
<h1>New product</h1>
<%= form_with model: @product do |form| %>
<div>
<%= form.label :name %> <!-- 「商品名」というラベルを表示 -->
<%= form.text_field :name %> <!-- 商品名を入力するテキストボックス -->
</div>
<div>
<%= form.submit %> <!-- 「Create Product」ボタンを表示 -->
</div>
<% end %>

form_with
って何ですか?

これはRailsの魔法の道具だよ!form_with
は、
- 自動的にセキュリティ対策をしてくれる
- 送信先のURLを自動で決めてくれる
- ボタンの文字も自動で決めてくれる
覚え方:form_with = フォーム・ウィズ = フォームと一緒に全部やってくれる
3-3. createアクション(実際に保存)
def create
# フォームから送られてきた安全なデータだけを使って新しい商品を作成
@product = Product.new(product_params)
if @product.save # データベースに保存を試みる
# 保存成功:商品詳細ページにリダイレクト
redirect_to @product
else
# 保存失敗:エラーメッセージと一緒にフォームを再表示
render :new, status: :unprocessable_entity
end
end
private
# セキュリティのため、許可されたパラメータのみを受け取る
def product_params
params.expect(product: [ :name ]) # 商品の名前のみ許可
end

product_params
って何ですか?なんで必要なんですか?

これは「セキュリティガード」だよ!
例えば、悪い人が「商品の価格を0円にしちゃおう」とか「管理者権限をもらっちゃおう」みたいな不正なデータを送ってきても、product_params
が「あ、それは許可されていません!」と止めてくれるんだ。
第4章:Read(読み取り)- 商品を見よう

実は、Readはもうできているんだよ!
def index
@products = Product.all # 全商品を取得(一覧表示用)
end
def show
@product = Product.find(params[:id]) # 特定の商品を取得(詳細表示用)
end

あ、本当ですね!indexとshowがReadなんですね。

その通り!
- index = 図書館の本棚全体を見る
- show = 特定の1冊を手に取って読む
こんなイメージだよ!
第5章:Update(更新)- 商品を編集しよう

更新は作成とよく似ているよ。
editとupdateの2つのアクションが必要なんだ。
5-1. editアクション(編集フォームを表示)
def edit
@product = Product.find(params[:id]) # 編集したい商品を取得
end
5-2. updateアクション(実際に更新)
def update
@product = Product.find(params[:id]) # 更新したい商品を取得
if @product.update(product_params) # 新しいデータで更新を試みる
# 更新成功:商品詳細ページにリダイレクト
redirect_to @product
else
# 更新失敗:エラーメッセージと一緒に編集フォームを再表示
render :edit, status: :unprocessable_entity
end
end

createとupdateって似てますね!

違いはこれだけだよ。
- create:
Product.new
→save
(新しく作って保存) - update:
Product.find
→update
(既存を見つけて更新)
第6章:DRY原則で賢くコーディング

今のコードを見ると、同じことを何度も書いていることは分かるかな?。まず、改善前のコードを見てみよう!
class ProductsController < ApplicationController
def show
@product = Product.find(params[:id]) # ←同じコード
end
def edit
@product = Product.find(params[:id]) # ←同じコード
end
def update
@product = Product.find(params[:id]) # ←同じコード
# 更新処理...
end
def destroy
@product = Product.find(params[:id]) # ←同じコード
# 削除処理...
end
end

あ、本当ですね!@product = Product.find(params[:id])
が4回も書いてある!

そうなんだ!これを「DRY原則」で改善しよう!

DRY原則って何ですか?

DRY = Don’t Repeat Yourself(同じことを繰り返すな)という意味だよ。

ということで、before_action
を使って、重複するコードをまとめよう!
class ProductsController < ApplicationController
# show, edit, update, destroyアクションの前に自動実行
before_action :set_product, only: %i[ show edit update destroy ]
def index
@products = Product.all # 全商品を取得
end
def show
# @productは既にset_productで設定済み!
# Product.find(params[:id])を書く必要がない
end
def new
@product = Product.new # 新しい商品オブジェクトを作成
end
def create
@product = Product.new(product_params) # フォームデータから商品を作成
if @product.save # 保存を試みる
redirect_to @product # 成功時は詳細ページへ
else
render :new, status: :unprocessable_entity # 失敗時はフォーム再表示
end
end
def edit
# @productは既にset_productで設定済み!
# Product.find(params[:id])を書く必要がない
end
def update
# @productは既にset_productで設定済み!
if @product.update(product_params) # 更新を試みる
redirect_to @product # 成功時は詳細ページへ
else
render :edit, status: :unprocessable_entity # 失敗時は編集フォーム再表示
end
end
def destroy
# @productは既にset_productで設定済み!
@product.destroy # データベースから削除
redirect_to products_path # 商品一覧ページにリダイレクト
end
private
def set_product
@product = Product.find(params[:id]) # IDから商品を検索
end
def product_params
params.expect(product: [ :name ]) # 許可されたパラメータのみ取得
end
end

わあ、すっきりしました!
4回書いていたコードが1回だけになりましたね!

そうだね!これの何がいいかというと、
- コードが短くなる: 同じことを何度も書かなくていい
- バグが減る: 修正は1箇所だけでOK
- 読みやすい: 何をしているか一目瞭然
例えば、もしProduct.find(params[:id])
をProduct.find(params[:product_id])
に変更したくなったら、改善前は4箇所を修正する必要があったけど、今は1箇所だけでいいんだ!

なるほど!修正し忘れでバグが起きることもなくなりますね。

その通り!before_action
は「アクションの前に自動で実行される準備係」だと思えばいいよ。
覚え方:before_action = 前もって準備 = アクションの前にお膳立てしてくれる
実際の動作はこんな感じです。
- ユーザーが商品詳細ページにアクセス
- Railsが「showアクションを実行するよ」と準備
- before_actionが「ちょっと待って!まず商品を探してくるね」
set_product
が実行されて@product
に商品が入る- やっと
show
アクションが実行される
第7章:パーシャルでビューもDRYに

コントローラーがすっきりしたら、今度はビューもDRYにしよう!
新規作成と編集で同じフォームを使っているから、パーシャル(部品)として切り出そう。
7-1. パーシャルファイル(_form.html.erb)
<%= form_with model: product do |form| %>
<div>
<%= form.label :name %> <!-- 商品名のラベル -->
<%= form.text_field :name %> <!-- 商品名の入力欄 -->
</div>
<div>
<%= form.submit %> <!-- 送信ボタン(自動でテキスト設定) -->
</div>
<% end %>
7-2. newビューで使用
<h1>New product</h1>
<%= render "form", product: @product %> <!-- パーシャルを呼び出し -->
<%= link_to "Cancel", products_path %> <!-- キャンセルリンク -->
7-3. editビューで使用
<h1>Edit product</h1>
<%= render "form", product: @product %> <!-- 同じパーシャルを使用 -->
<%= link_to "Cancel", @product %> <!-- キャンセルリンク -->

パーシャルって何ですか?

パーシャルは「部品」だよ!
例えば、LEGOブロックを想像してみて。同じパーツを色んな場所で使い回せるでしょ?パーシャルも同じで、同じビューの部品を色んなページで使い回せるんだ。
Point:
- パーシャル = 部品 = 使い回せる画面の部品
- ファイル名は_(アンダースコア)で始まる
第8章:Delete(削除)- 商品を削除しよう

最後は削除機能だ!これが一番シンプルだよ。
def destroy
@product.destroy # 商品をデータベースから削除
redirect_to products_path # 商品一覧ページにリダイレクト
end
削除ボタンの作成(show.html.erb)
<h1><%= @product.name %></h1>
<%= link_to "Back", products_path %> <!-- 戻るリンク -->
<%= link_to "Edit", edit_product_path(@product) %> <!-- 編集リンク -->
<%= button_to "Delete", @product, method: :delete,
data: { turbo_confirm: "Are you sure?" } %> <!-- 削除ボタン -->

turbo_confirm
って何ですか?

これは「本当に削除していいですか?」という確認ダイアログを表示してくれるんだ。間違って削除ボタンを押しちゃった時の「あー!」を防いでくれる優しい機能だよ。
覚え方:turbo_confirm = ターボ確認 = 高速で確認してくれる
第9章:完成したコントローラー

さあ、完成したコントローラーを見てみよう!
class ProductsController < ApplicationController
# 指定されたアクションの前に自動実行される準備メソッド
before_action :set_product, only: %i[ show edit update destroy ]
# C-R-U-D の R: 全商品を読み取り(一覧表示)
def index
@products = Product.all # 全ての商品をデータベースから取得
end
# C-R-U-D の R: 特定商品を読み取り(詳細表示)
def show
# @productは既にset_productで設定済み
end
# C-R-U-D の C: 新規作成フォームを表示
def new
@product = Product.new # 空の商品オブジェクトを作成
end
# C-R-U-D の C: 新しい商品を実際に作成・保存
def create
@product = Product.new(product_params) # 安全なパラメータで商品作成
if @product.save # データベースへの保存を試みる
redirect_to @product # 成功:詳細ページへリダイレクト
else
# 失敗:エラーメッセージと共にフォーム再表示
render :new, status: :unprocessable_entity
end
end
# C-R-U-D の U: 編集フォームを表示
def edit
# @productは既にset_productで設定済み
end
# C-R-U-D の U: 商品を実際に更新
def update
if @product.update(product_params) # 更新を試みる
redirect_to @product # 成功:詳細ページへリダイレクト
else
# 失敗:エラーメッセージと共に編集フォーム再表示
render :edit, status: :unprocessable_entity
end
end
# C-R-U-D の D: 商品を削除
def destroy
@product.destroy # データベースから商品を削除
redirect_to products_path # 商品一覧ページへリダイレクト
end
private
# 共通処理:IDから商品を検索して@productに設定
def set_product
@product = Product.find(params[:id])
end
# セキュリティ:許可されたパラメータのみを取得
def product_params
params.expect(product: [ :name ]) # 商品名のみ許可
end
end
第10章:まとめ – CRUDを覚えよう!

プロ太先生、ありがとうございました!CRUDがよく分かりました。これでブログシステムも、ECサイトも、SNSも作れそうですね!

その通り!CRUDはWebアプリケーションの基本中の基本。これをマスターすれば、どんなアプリでも作れるようになるよ。頑張って練習してね!
Railsのルール
- DRY原則: 同じコードは書かない →
before_action
やパーシャルを使う - Strong Parameters: セキュリティのため、許可されたデータのみ受け取る
- エラーハンドリング: 成功時はリダイレクト、失敗時は再表示
付録:よく使うRailsのメソッド一覧
コントローラーでよく使うメソッド
find(id)
: IDで1件検索all
: 全件取得new
: 新しいオブジェクト作成save
: データベースに保存update
: データベースの更新destroy
: データベースから削除redirect_to
: 別のページにリダイレクトrender
: ビューを表示
ビューでよく使うヘルパー
link_to
: リンクを作成button_to
: ボタンを作成form_with
: フォームを作成render
: パーシャルを呼び出し
覚えておくと便利だよ!