Rails CRUD操作を学ぼう!初心者向け完全ガイド

第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は、

  1. 自動的にセキュリティ対策をしてくれる
  2. 送信先のURLを自動で決めてくれる
  3. ボタンの文字も自動で決めてくれる

覚え方: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.newsave(新しく作って保存)
  • update: Product.findupdate(既存を見つけて更新)

第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. コードが短くなる: 同じことを何度も書かなくていい
  2. バグが減る: 修正は1箇所だけでOK
  3. 読みやすい: 何をしているか一目瞭然

例えば、もしProduct.find(params[:id])Product.find(params[:product_id])に変更したくなったら、改善前は4箇所を修正する必要があったけど、今は1箇所だけでいいんだ!

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

その通り!before_actionは「アクションの前に自動で実行される準備係」だと思えばいいよ。

覚え方:before_action = 前もって準備 = アクションの前にお膳立てしてくれる

実際の動作はこんな感じです。

  1. ユーザーが商品詳細ページにアクセス
  2. Railsが「showアクションを実行するよ」と準備
  3. before_actionが「ちょっと待って!まず商品を探してくるね」
  4. set_productが実行されて@productに商品が入る
  5. やっと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のルール

  1. DRY原則: 同じコードは書かない → before_actionやパーシャルを使う
  2. Strong Parameters: セキュリティのため、許可されたデータのみ受け取る
  3. エラーハンドリング: 成功時はリダイレクト、失敗時は再表示

付録:よく使うRailsのメソッド一覧

コントローラーでよく使うメソッド

  • find(id): IDで1件検索
  • all: 全件取得
  • new: 新しいオブジェクト作成
  • save: データベースに保存
  • update: データベースの更新
  • destroy: データベースから削除
  • redirect_to: 別のページにリダイレクト
  • render: ビューを表示

ビューでよく使うヘルパー

  • link_to: リンクを作成
  • button_to: ボタンを作成
  • form_with: フォームを作成
  • render: パーシャルを呼び出し

覚えておくと便利だよ!