2020/12/18~2020/12/19

 

 今回の内容

 

 

・商品詳細表示機能の実装

 

・詳細ページの編集

前回の疑問点

 

トップページでは画像のリンクを

<%= 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のように調べて補足内容がわかったらっ忘れないようにここでアウトプットしていく