今回の内容
・商品詳細表示機能の実装
・詳細ページの編集
前回の疑問点
トップページでは画像のリンクを
<%= image_tag item.image, class: "item-img" %>
と書いていたが
詳細ページでは
<%= image_tag @item.image, class:"item-box-img" if @item.image.attached? %>
と@を付けないとエラーになった理由
メンターさんに質問する前に自分でもう一度コードをみていたら
トップページは
<% @items.each do |item| %>
<li class='list'>
<%= link_to item_path(item.id), method: :get do %>
<div class='item-img-content'>
<%= image_tag item.image, class: "item-img" %>
1行目でitemを定義していたため使えているということがわかった
念のためメンターさんにも確認したところ
その解釈で合っていて、コントローラーに定義しないとビューに反映させることはできないと教えていただきました。
商品詳細ページは細かいところを直しLGTM をもらった
・商品詳細表示機能の実装
・editとupdateのMVCを追加
newとcreateアクションとほぼ同じ実装
updateのエラーメッセージを表示させる際に
エラーが発生
内容はupdateメソッドでmodelがないというエラーだった
ビューのコード
<%= form_with model: @item, local: true do |f| %>
<%= render 'shared/error_messages', model: f.object %>
コントローラのコード
def edit
@item = Item.find(params[:id])
end
def update
item = Item.find(params[:id])
item.update(item_params)
if item.save
redirect_to item_path
else
render :edit
end
end
ビューのrenderエラーメッセージのコードの引数が@itemに対して、コントローラーでのupdeteの記述がitemで書いていたことが原因だった
def update
@item = Item.find(params[:id])
@item.update(item_params)
if @item.save
redirect_to item_path
else
render :edit
end
end
このように直して解決した。
コントローラーのコードが
class ItemsController < ApplicationController
before_action :authenticate_user!, only: [:new]
def index
@items = Item.includes(:user).order('created_at DESC')
end
def new
@item = Item.new
end
def create
@item = Item.new(item_params)
if @item.save
redirect_to root_path
else
render :new
end
end
def show
@item = Item.find(params[:id])
end
def edit
@item = Item.find(params[:id])
end
def update
@item = Item.find(params[:id])
if @item.update(item_params)
redirect_to item_path
else
render :edit
end
end
private
def item_params
params.require(:item).permit(:image, :name, :explanation, :price, :category_id, :status_id, :deliver_fee_id, :shipping_area_id, :shipping_day_id).merge(user_id: current_user.id)
end
end
このように
@item = Item.find(params[:id])
を3回記述している
railsでは同じ記述は繰り返し書かないようにしたい
before_actionにまとめたいがメソッド化しないと記述できない
よって
class ItemsController < ApplicationController
before_action :authenticate_user!, only: [:new]
before_action :item_find, only: [:show, :edit, :update]
def index
@items = Item.includes(:user).order('created_at DESC')
end
def new
@item = Item.new
end
def create
@item = Item.new(item_params)
if @item.save
redirect_to root_path
else
render :new
end
end
def show
end
def edit
end
def update
if @item.update(item_params)
redirect_to item_path
else
render :edit
end
end
private
def item_params
params.require(:item).permit(:image, :name, :explanation, :price, :category_id, :status_id, :deliver_fee_id, :shipping_area_id, :shipping_day_id).merge(user_id: current_user.id)
end
def item_find
@item = Item.find(params[:id])
end
end
privateにメソッドとして記述することでまとめることができる
補足: before_actionで特定のアクションのみ使いたい場合はonlyだが
特定のアクションのみ使いたくない場合はexceptと記述する
感想
メンターさんに質問してみると、自分の見落としですぐに解決することが多い
もう少し自分で考えてから質問していきたい
今回のbefore_actionのように調べて補足内容がわかったらっ忘れないようにここでアウトプットしていく