🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1311閲覧

showとindexアクションとで同じモデルを参照しているはずがidがずれておりエラーが出る

ketyan

総合スコア22

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2019/11/19 10:29

編集2019/11/19 12:14

###現状
現在railsでアプリを作っています。
indexページでモデルを一覧表示し、モデルをクリックしたら対応するモデルの
showページにアクセスできるようにしたいと考えています。

ローカルサーバーでアプリを起動したところindexページは表示されるのですが、
モデルをクリックするとshowページアクセスできずに以下のエラーが起きてしまいます。
ちなみにshowページのurlで直接アクセスすることは出来ました。
###エラーログ

ErrorLog

1Started GET "/souvenirs/%23%3CSouvenir::ActiveRecord_Relation:0x00005571498e3450%3E" for ::1 at 2019-11-19 18:52:07 +0900 2Processing by SouvenirsController#show as HTML 3 Parameters: {"id"=>"#<Souvenir::ActiveRecord_Relation:0x00005571498e3450>"} 4 Souvenir Load (0.6ms) SELECT "souvenirs".* FROM "souvenirs" WHERE "souvenirs"."id" = ? LIMIT ? [["id", 0], ["LIMIT", 1]] 5 ↳ app/controllers/souvenirs_controller.rb:23 6Completed 404 Not Found in 28ms (ActiveRecord: 0.6ms) 7 8 9 10ActiveRecord::RecordNotFound (Couldn't find Souvenir with 'id'=#<Souvenir::ActiveRecord_Relation:0x00005571498e3450>): 11 12app/controllers/souvenirs_controller.rb:23:in `show'

indexページのインスタンス変数@souvenis
showページのインスタンス変数@souvenirをdebuggerで確認したところ
同じモデルを参照しているつもりがidが異なっていました。

Show

1(byebug) @souvenir 2#<Souvenir id: 980190963, name: "MyString", spot: "MyString", price: 1, good: nil, picture: "20191119191038.jpg", genre: "MyString", comment: "MyString", created_at: "2019-11-19 10:10:38", updated_at: "2019-11-19 10:10:38">

index

1byebug) @souvenirs 2#<ActiveRecord::Relation [#<Souvenir id: 298486374, name: "MyString", spot: "MyString", price: 1, good: 1, picture: "MyString", genre: "MyString", comment: "MyText", created_at: "2019-11-19 09:34:17", updated_at: "2019-11-19 09:34:17">, #<Souvenir id: 980190962, name: "MyString", spot: "MyString", price: 1, good: 1, picture: "MyString", genre: "MyString", comment: "MyText", created_at: "2019-11-19 09:34:17", updated_at: "2019-11-19 09:34:17">]>

###原因予想
indexページでgemのwill_paginateを使用しているため、@souvenirsの
idの取得法がshowアクションと異なっているからかと考えています。
しかしながら正しいidの渡し方が分からず、質問させていただきました。

SouvenirsController

1class SouvenirsController < ApplicationController 2 3 def new 4 @souvenir = Souvenir.new 5 flash[:info] = "項目を記入してください" 6 end 7 8 def index 9 @souvenirs = Souvenir.paginate(page: params[:page], per_page: 5) 10 end 11 12 def create 13 @souvenir = Souvenir.create(souvenir_params) 14 if @souvenir.save 15 flash[:success] = "投稿に成功しました" 16 redirect_to action: 'index' 17 else 18 render 'new' 19 end 20 end 21 22 def show 23 @souvenir = Souvenir.find(params[:id]) 24 end 25 26 def edit 27 @souvenir = Souvenir.find(params[:id]) 28 end 29 30 def update 31 end 32 33 def destroy 34 end 35 36 private 37 38 def souvenir_params 39 params.require(:souvenir).permit(:name, :spot, :price, :picture, :genre, :comment) 40 end 41end

viewページを追記しておきます。

私の前回の質問と少しかぶりますが、
showとindexはほぼ中身が同じなのでパーシャルを使いまわしたいです。
しかしshowページのrenderメソッドで、collectionに渡す@souvenirが認識されず、パーシャルを使えていません。

ShowView

1<div class = "row souvenir_box"> 2 <div class = "souvenir_name col-sm-12"><%= @souvenir.name%></div> 3 <div class = "col-sm-8"> 4 <div class="row"> 5 <div class = "souvenir_spot col-sm-12 souvenir_text-items "><%= @souvenir.spot%></div> 6 <div class = "souvenir_price col-sm-12 souvenir_text-items"><%= @souvenir.price%></div> 7 <div class = "souvenir_genre col-sm-12 souvenir_text-items"><%= @souvenir.genre%></div> 8 </div> 9 </div> 10 <div class = "col-sm-4"> 11 <% if @souvenir.picture? %> 12   <%= image_tag @souvenir.picture.thumb.url %> 13  <% else %> 14 <p>noimages</p> 15 <% end %> 16 </div> 17 <div class = "col-sm-12"><%= @souvenir.comment%></div> 18</div> 19 20

IndexView

1<%= will_paginate @souvenirs %> 2<%= render partial:"souvenir", collection: @souvenirs %> 3<%= will_paginate @souvenirs %>

Partial

1<%= link_to souvenir_path(@souvenirs) do %> 2<div class = "row souvenir_box"> 3 <div class = "souvenir_name col-sm-12"><%= souvenir.name%></div> 4 <div class = "col-sm-8"> 5 <div class="row"> 6 <div class = "souvenir_spot col-sm-12 souvenir_text-items "><%= souvenir.spot%></div> 7 <div class = "souvenir_price col-sm-12 souvenir_text-items"><%= souvenir.price%></div> 8 <div class = "souvenir_genre col-sm-12 souvenir_text-items"><%= souvenir.genre%></div> 9 </div> 10 </div> 11 <div class = "col-sm-4"> 12 <% if souvenir.picture? %> 13   <%= image_tag souvenir.picture.thumb.url %> 14  <% else %> 15 <p>noimages</p> 16 <% end %> 17 </div> 18</div> 19<% end %>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

winterboum

2019/11/19 11:13

index の viewも追加シて下さい
ketyan

2019/11/19 12:15

index,show両方のviewを追加させていただきました。
guest

回答1

0

ベストアンサー

index の @souvenirs は複数の Souveir で show の@souvenir は一つのSouvenirですから、idが異なるのが当然です。

partialは一つのSouvenirを表示させるつもりですか?複数ですか?
一つだとすると
<%= link_to souvenir_path(@souvenirs) do %>と複数を当てているのがまずいです。
また do の中で souvenir.name などsouvenir を参照していますが、これ未定義のエラーになりませんか?
showとpartialを共有するなら
<%= render partial:"souvenir", collection: @souvenirs %>

<% @souvenirs.each do | souvenir | %> <%= <%= render partial:"souvenir", locals: {souvenir: souvenir} %>

とし、
partial側の<%= link_to souvenir_path(@souvenirs) do %><%= link_to souvenir_path(souvenir) do %>とするのが良いでしょう。

投稿2019/11/19 12:52

winterboum

総合スコア23567

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ketyan

2019/11/19 13:55

ご回答ありがとうございます。 localsオプションを使えば簡単な話だったんですね。おかげさまで無事viewファイルを修正することが出来ました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問