Rails学習における「編集機能(edit/update)」の実装を通じて、MVCがどのようにバトンを繋ぎ、データの正確性を守っているのかを深く掘り下げます。
- 実装の全体像(What)と具体的なコード解説
商品編集機能は、以下の4つの要素が連携して完成します。
① ルーティング:リクエストの「入り口」
ファイル: config/routes.rb
# edit(表示)と update(更新)アクションへのパスを生成
resources :items, only: [:index, :new, :create, :show, :edit, :update]
Railsの「地図」を広げる作業です。URL(/items/:id/edit)と、動かすべきコントローラーのアクションを紐付けます。これがないと「No Route Error」が発生します。
② コントローラー:現場の司令塔とガードマン
ファイル: app/controllers/items_controller.rb
class ItemsController < ApplicationController
#1. 前処理(フィルタ)で安全性を確保
before_action :authenticate_user!, only: [:edit, :update]
before_action :set_item, only: [:show, :edit, :update]
before_action :move_to_index, only: [:edit, :update]
def update
# 2. updateメソッドを呼んだ瞬間にモデルのバリデーションが走る
if @item.update(item_params)
redirect_to item_path(@item.id) # 成功:詳細ページへ
else
# 失敗:入力内容を保持して編集画面を再表示
render :edit, status: :unprocessable_entity
end
end
private
def set_item
@item = Item.find(params[:id])
end
def move_to_index
# 出品者本人以外がアクセスしてきたらトップページへリダイレクト
redirect_to root_path unless current_user.id == @item.user_id
end
end
なぜ before_action で本人確認をするのか?
ビューで編集ボタンを非表示にするだけでは、URL(/items/商品ID/edit)を直接入力する「URL直打ち」の攻撃を防げません。サーバーサイドの入り口で物理的にアクセスを遮断することで、他人の商品データを改ざんされるリスクを根本から排除しています。
なぜ保存失敗時に render :edit を使うのか?
redirect_to(新しいリクエストを送り直す)を使うと、ユーザーがせっかく入力した内容が消えてしまいます。 render を使えば、入力途中のデータ(@itemの中身)を保持したまま画面を表示できるため、ユーザーは間違った箇所だけを直すことができ、UX(ユーザー体験)が向上します。
③ モデル:データの正確性を守る「番人」
ファイル: app/models/item.rb
# データの正しさを判定する
validates :name, :info, :price, :image, presence: true
validates :price, numericality: { only_integer: true, greater_than_or_equal_to: 300 }
バリデーションは、不適切なデータをDBに入れないための最終防衛ラインです。保存・更新の直前に自動で発動し、ルール違反があればエラーメッセージを生成します。
④ ビュー:ユーザーへの「窓口」と「hoge」の解消
ファイル: app/views/items/edit.html.erb
<%= form_with model: @item, local: true do |f| %>
<%# エラー理由を表示し、ユーザーに修正を促す %>
<%= render 'shared/error_messages', model: f.object %>
<%# 仮名「hoge」を実際のカラム名(:name等)に書き換える %>
<%= f.text_area :name, class:"items-text" %>
...
<% end %>
なぜ「hoge」をカラム名に書き換えるのか?
テンプレートにある :hoge は単なる目印です。これを :name や :price に書き換えることで、Railsの**「データバインディング」**が機能します。
初期値の表示: form_with がモデルオブジェクトから値を自動抽出し、編集画面を開いた瞬間に「以前入力した内容」を表示してくれます。
更新の正確性: 入力された値がどのカラム(名前なのか、価格なのか)に対応するかをRailsが正しく認識できるようになります。