質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

2033閲覧

Rails5.2で、includesメソッドを使って関連しているテーブルの値を取得したいのですが上手くいかないので教えてください。

sassan738

総合スコア32

Ruby on Rails 5

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2020/06/16 14:22

Railsの学習のためにゲームソフトのユーザーレビューサイトを制作しています。

環境は
Rails 5.2.4
Ruby 2.6.5
PostgreSQL
Docker Compose
です。

gameテーブルとreviewsテーブルをGame has_many reviews, Review belogs_to Gameの関係で関連づけしてincludesメソッドを使用して、指定したgameに関連するreviewを取得したいです。
それぞれのファイルは以下の通りです。

game.rb

class Game < ApplicationRecord belongs_to :user has_many :reviews, dependent: :destroy 以下略

review.rb

class Review < ApplicationRecord belongs_to :user belongs_to :game 以下略

games_controller.rb

class GamesController < ApplicationController include ReviewsHelper before_action :logged_in_user, except: [:index, :show] before_action :admin_user, except: [:index, :show] before_action :find_resource, except: [:index, :new, :create, :show] def index @games = Game.order_desc.page(params[:page]).per(6) end def new @game = current_user.games.new end def create @game = current_user.games.new(game_params) if @game.save flash[:info] = "ゲームデータが登録されました" redirect_to @game else render 'new' end end def show games = Game.includes(:reviews) @reviews = games.find{|g| g.id == params[:id]}.reviews end def edit end def update if @game.update_attributes(game_params) flash[:success] = "ゲームデータが更新されました" redirect_to @game else render "edit" end end def destroy if @game.destroy flash[:success] = "ゲームデータが削除されました" redirect_to root_path else flash[:danger] = "ゲームデータは存在しません" redirect_to root_path end end private def game_params params.require(:game).permit(:title, :developer, :release_date, :summary, :jacket, :youtube_video_id) end def find_resource @game = Game.find(params[:id]) end end

games_controller.rbのshowメソッドで@reviews変数に格納したレビューデータをviews/games/show.html.erbにて表示したいのですが以下のようなエラーが出ます。
イメージ説明
その時のログは以下の通りです。

Started GET "/games/35" for 172.18.0.1 at 2020-06-16 14:08:22 +0000 Cannot render console from 172.18.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by GamesController#show as HTML Parameters: {"id"=>"35"} Game Load (1.1ms) SELECT "games".* FROM "games" ↳ app/controllers/games_controller.rb:27 Review Load (1.2ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_id" IN ($1, $2, $3, $4, $5, $6, $7) [["game_id", 37], ["game_id", 39], ["game_id", 35], ["game_id", 42], ["game_id", 43], ["game_id", 40], ["game_id", 41]] ↳ app/controllers/games_controller.rb:27 Completed 500 Internal Server Error in 11ms (ActiveRecord: 2.3ms) NoMethodError (undefined method `reviews' for nil:NilClass): app/controllers/games_controller.rb:27:in `show'

ログを見る感じだと、showメソッドのgames = Game.includes(:reviews)のところでgameの入った配列が取得できていないように思います。
ちなみにrails consoleで同じ内容を実行した時にはreviewデータが取得できています。

irb(main):005:0> games = Game.includes(:reviews) Game Load (1.1ms) SELECT "games".* FROM "games" LIMIT $1 [["LIMIT", 11]] Review Load (1.6ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_id" IN ($1, $2, $3, $4, $5, $6, $7) [["game_id", 37], ["game_id", 39], ["game_id", 35], ["game_id", 42], ["game_id", 43], ["game_id", 40], ["game_id", 41]] => #<ActiveRecord::Relation [#<Game id: 37, user_id: 1, title: "ペルソナ5 ザ・ロイヤル", developer: "アトラス", release_date: "2019-10-31 00:00:00", summary: "全世界累計セールス270万本を突破したピカレスク・ジュブナイルRPG「ペルソナ5」が、多数の追加要素...", created_at: "2020-06-07 16:56:10", updated_at: "2020-06-07 16:56:10", youtube_video_id: "o9QjlLdYK5I">, #<Game id: 39, user_id: 1, title: "アサシン クリード オリジンズ デラックスエディション", developer: "UBIsoft", release_date: "2019-07-11 00:00:00", summary: "ストーリー<br>首都アレクサンドリアから遠く、広大な砂漠の中に孤立するように存在するシワオアシス。...", created_at: "2020-06-07 16:56:10", updated_at: "2020-06-07 16:56:10", youtube_video_id: "fBTFF9GNOV0">, #<Game id: 35, user_id: 1, title: "あつまれ どうぶつの森", developer: "任天堂", release_date: "2020-03-20 00:00:00", summary: "無人島移住\r\nではじまる自由気ままな楽園生活\r\n現実と同じ時間\r\nが流れる世界で、\r\n自由気ままに暮...", created_at: "2020-06-07 16:56:10", updated_at: "2020-06-16 07:47:34", youtube_video_id: "UcB9KrrD26M"> 以下略 irb(main):006:0> reviews = games.find{|g| g.id == 35}.reviews Game Load (1.0ms) SELECT "games".* FROM "games" Review Load (1.2ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_id" IN ($1, $2, $3, $4, $5, $6, $7) [["game_id", 37], ["game_id", 39], ["game_id", 35], ["game_id", 42], ["game_id", 43], ["game_id", 40], ["game_id", 41]] => #<ActiveRecord::Associations::CollectionProxy [#<Review id: 126, score: 9, title: "49 hoge", review: "49 fugafugafugafugafuga<br>fugafugafugafugafuga", user_id: 49, game_id: 35, created_at: "2020-06-12 15:51:01", updated_at: "2020-06-12 15:51:01">, #<Review id: 79, score: 2, title: "2 hoge", review: "2 fugafugafugafugafuga<br>fugafugafugafugafuga", user_id: 2, game_id: 35, created_at: "2020-06-12 15:51:00", updated_at: "2020-06-12 15:51:00">, #<Review id: 80, score: 3, title: "3 hoge", review: "3 fugafugafugafugafuga<br>fugafugafugafugafuga", user_id: 3, game_id: 35, created_at: "2020-06-12 15:51:00", updated_at: "2020-06-12 15:51:00">

どうすればいいのか分からないのでアドバイスが頂きたです。
よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

params[:id]には文字列が来るかと思います。データベースのIDが整数で入っていれば、比較しても一致しません。

投稿2020/06/16 14:26

maisumakun

総合スコア145184

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

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

maisumakun

2020/06/16 14:28 編集

gamesの取得ができていないのではなく、findに失敗しているのではないか、と考えます。 というより、includesなど使わずに「@reviews = Review.where(game_id: params[:id])」と引くほうが適切かもしれません。
sassan738

2020/06/16 14:30

回答いただきありがとうございます。 to_iメソッドでparamsを整数に変換すると取得することができました。
sassan738

2020/06/16 14:36

最初はshowメソッドで以下のような形で取得していたのですが、 @game = Game.find(params[:id]) @reviews = @game.reviews.review_with_value.page(params[:page]).per(10) メンターさんから「パフォーマンスを向上させるためにincludesでキャッシュしておいた方が良いです」とのアドバイスを頂いて、includesで取得する方法を考えていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問