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

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

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

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

Ruby on Rails 6

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

Q&A

1回答

325閲覧

【Rails】アソシエーションを多対多で定義してるテーブルの外部キーを取得したい

ddsky

総合スコア0

Ruby

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

Ruby on Rails 6

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

0グッド

0クリップ

投稿2022/11/17 01:44

やりたいこと

  • 多対多アソシエーションを定義しているテーブル先の外部キーを取得したい

前提

アルバイト情報交流サイトを作成しています。
Jobsテーブルにアルバイト名を、purpose_typesテーブルにはバイトの種類(稼げる、楽しいなど)、これらの中間テーブルであるjob_purpose_typesテーブルにはjob_id、purpose_type_idを保存します。
各、purpose_type、showページにていいね数を基準とした人気ランキングを設けたいです。
purpose_typesコントローラーのshowアクションにて、@all_ranksの情報を元に、@each_ranksで実現させようとしています。
そのランキング機能で「job_id」の情報が欲しくて取得したいのですが、参照できず困っています。
中間テーブルの情報は参照できないのでしょうか。

発生している問題・エラーメッセージ

エラーメッセージ undefined method `job_id' for #<Review::ActiveRecord_Associations_CollectionProxy:0x00007fc19ff68548> @each_ranks = @all_ranks.select{ |job| job.reviews.job_id == params[:id] }の記載の時 のログ Started GET "/purpose_types/1" for ::1 at 2022-11-17 10:32:56 +0900 (206.2ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), NoMethodError - undefined method `job_id' for #<Review::ActiveRecord_Associations_CollectionProxy:0x00007fc19ff68548>: app/controllers/purpose_types_controller.rb:19:in `block in show' app/controllers/purpose_types_controller.rb:19:in `show' Started POST "/__better_errors/8099fd75adf892cd/variables" for ::1 at 2022-11-17 10:32:59 +0900 Review Load (33.6ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`job_id` = 1 LIMIT 11 CACHE Review Load (0.0ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`job_id` = 1 LIMIT 11 Job Load (68.7ms) SELECT `jobs`.* FROM `jobs` INNER JOIN `job_purpose_types` ON `jobs`.`id` = `job_purpose_types`.`job_id` WHERE `job_purpose_types`.`purpose_type_id` = 1 LIMIT 11 CACHE Job Load (0.0ms) SELECT `jobs`.* FROM `jobs` INNER JOIN `job_purpose_types` ON `jobs`.`id` = `job_purpose_types`.`job_id` WHERE `job_purpose_types`.`purpose_type_id` = 1 LIMIT 11

@each_ranks = @all_ranks.select{ |job| job.job_purpose_types.job_id == params[:id] }の記載の時のログ

undefined method `job_id' for #JobPurposeType::ActiveRecord_Associations_CollectionProxy:0x00007fc1a78165a8

NoMethodError - undefined method `job_id' for #<Review::ActiveRecord_Associations_CollectionProxy:0x00007fc19ff68548>: app/controllers/purpose_types_controller.rb:19:in `block in show' app/controllers/purpose_types_controller.rb:19:in `show' Started POST "/__better_errors/8099fd75adf892cd/variables" for ::1 at 2022-11-17 10:32:59 +0900 Review Load (33.6ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`job_id` = 1 LIMIT 11 CACHE Review Load (0.0ms) SELECT `reviews`.* FROM `reviews` WHERE `reviews`.`job_id` = 1 LIMIT 11 Job Load (68.7ms) SELECT `jobs`.* FROM `jobs` INNER JOIN `job_purpose_types` ON `jobs`.`id` = `job_purpose_types`.`job_id` WHERE `job_purpose_types`.`purpose_type_id` = 1 LIMIT 11 CACHE Job Load (0.0ms) SELECT `jobs`.* FROM `jobs` INNER JOIN `job_purpose_types` ON `jobs`.`id` = `job_purpose_types`.`job_id` WHERE `job_purpose_types`.`purpose_type_id` = 1 LIMIT 11 Started GET "/purpose_types/1" for ::1 at 2022-11-17 10:37:47 +0900 Processing by PurposeTypesController#show as HTML Parameters: {"id"=>"1"} PurposeType Load (0.8ms) SELECT `purpose_types`.* FROM `purpose_types` WHERE `purpose_types`.`id` = 1 LIMIT 1 ↳ app/controllers/purpose_types_controller.rb:58:in `set_purpose_type' User Load (1.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1 Job Load (0.6ms) SELECT `jobs`.* FROM `jobs` WHERE `jobs`.`id` = 1 LIMIT 1 ↳ app/controllers/purpose_types_controller.rb:10:in `show' (0.6ms) SELECT `likes`.`job_id` FROM `likes` GROUP BY `likes`.`job_id` ORDER BY count(job_id) desc LIMIT 10 ↳ app/controllers/purpose_types_controller.rb:13:in `show' Job Load (0.5ms) SELECT `jobs`.* FROM `jobs` WHERE `jobs`.`id` IN (1, 2) ↳ app/controllers/purpose_types_controller.rb:13:in `show' JobPurposeType Load (0.6ms) SELECT `job_purpose_types`.* FROM `job_purpose_types` WHERE `job_purpose_types`.`job_id` = 1 LIMIT 11 Completed 500 Internal Server Error in 529ms (ActiveRecord: 330.6ms | Allocations: 29700) CACHE JobPurposeType Load (0.0ms) SELECT `job_purpose_types`.* FROM `job_purpose_types` WHERE `job_purpose_types`.`job_id` = 1 LIMIT 11 CACHE JobPurposeType Load (0.0ms) SELECT `job_purpose_types`.* FROM `job_purpose_types` WHERE `job_purpose_types`.`job_id` = 1 LIMIT 11 NoMethodError - undefined method `job_id' for #<JobPurposeType::ActiveRecord_Associations_CollectionProxy:0x00007fc1a78165a8>: app/controllers/purpose_types_controller.rb:19:in `block in show' app/controllers/purpose_types_controller.rb:19:in `show' Started POST "/__better_errors/adb9006a985b2c7a/variables" for ::1 at 2022-11-17 10:37:48 +0900 JobPurposeType Load (14.8ms) SELECT `job_purpose_types`.* FROM `job_purpose_types` WHERE `job_purpose_types`.`job_id` = 1 LIMIT 11 CACHE JobPurposeType Load (0.0ms) SELECT `job_purpose_types`.* FROM `job_purpose_types` WHERE `job_purpose_types`.`job_id` = 1 LIMIT 11 Job Load (2.1ms) SELECT `jobs`.* FROM `jobs` INNER JOIN `job_purpose_types` ON `jobs`.`id` = `job_purpose_types`.`job_id` WHERE `job_purpose_types`.`purpose_type_id` = 1 LIMIT 11 CACHE Job Load (0.0ms) SELECT `jobs`.* FROM `jobs` INNER JOIN `job_purpose_types` ON `jobs`.`id` = `job_purpose_types`.`job_id` WHERE `job_purpose_types`.`purpose_type_id` = 1 LIMIT 11

該当のソースコード

purpose_types_controller.rb

1 before_action :set_purpose_type, only: [:show, :edit, :update, :destroy] 2345 def show 6 @job = Job.find(params[:id]) 7 @jobs = @purpose_type.jobs 8 @all_ranks = Job.find(Like.group(:job_id).order('count(job_id) desc').limit(10).pluck(:job_id)) 9 10 #@all_ranksでJobのインスタンス取れている 11 12 @each_ranks = @all_ranks.select{ |job| job.reviews.job_id == params[:id] } 13 14 end 15161718 19 private 20 21 def set_purpose_type 22 @purpose_type = PurposeType.find(params[:id]) 23 end 24end

purpose_types/show.html.erb

1<h2><%= @purpose_type.name %></h2> 2 3 4<% @each_ranks.each.with_index(1) do |job, i| %><br> 5 <%= i %>位 6 <%= link_to "#{job.name}", job_reviews_path(job) %> 7<% end %><br> 8 9 10<% @jobs.each do |job| %> 11 <%= job.name %> 12 <% if job.liked?(current_user) %> 13 <%= link_to "/likes/job/#{job.id}", method: :delete do %> 14 <span style="color:red;">❤︎</span> 15 <%= job.likes.count %> 16 <% end %> 17 <% else %> 18 <% # TODO: like コントローラに、job.id を POST でリクエストする %> 19 <%= link_to "/likes/job/#{job.id}", method: :post do %> 20 <span>❤︎</span> 21 <%= job.likes.count %> 22 <% end %> 23 <% end %> 24<% end %><br> 25 26<%= link_to "戻る" , root_path %> 27

Job.rb

1# == Schema Information 2# 3# Table name: jobs 4# 5# id :bigint not null, primary key 6# name :string(255) 7# created_at :datetime not null 8# updated_at :datetime not null 9# 10class Job < ApplicationRecord 11 has_many :job_purpose_types 12 has_many :purpose_types, through: :job_purpose_types 13 has_many :users, through: :likes 14 has_many :likes, dependent: :destroy 15 has_many :reviews 16 17 def liked?(user) 18 likes.where(user_id: user.id).exists? 19 end 20end

purpose_type.rb

1# == Schema Information 2# 3# Table name: purpose_types 4# 5# id :bigint not null, primary key 6# name :string(255) 7# created_at :datetime not null 8# updated_at :datetime not null 9# category_purpose_type_id :bigint 10# 11# Indexes 12# 13# index_purpose_types_on_category_purpose_type_id (category_purpose_type_id) 14# 15# Foreign Keys 16# 17# fk_rails_... (category_purpose_type_id => category_purpose_types.id) 18# 19class PurposeType < ApplicationRecord 20 has_many :job_purpose_types 21 has_many :jobs, through: :job_purpose_types 22 validates :name, uniqueness: true 23 24 25 def liked?(user) 26 likes.where(user_id: user.id).exists? 27 end 28end 29

job_purpose_type.rb

1# == Schema Information 2# 3# Table name: job_purpose_types 4# 5# id :bigint not null, primary key 6# created_at :datetime not null 7# updated_at :datetime not null 8# job_id :bigint 9# purpose_type_id :bigint 10# 11# Indexes 12# 13# index_job_purpose_types_on_job_id (job_id) 14# index_job_purpose_types_on_purpose_type_id (purpose_type_id) 15# 16# Foreign Keys 17# 18# fk_rails_... (job_id => jobs.id) 19# fk_rails_... (purpose_type_id => purpose_types.id) 20# 21class JobPurposeType < ApplicationRecord 22 belongs_to :job 23 belongs_to :purpose_type 24end 25

試したこと

・ 別テーブルのjob_idカラムを取得しようとした

@each_ranks = @all_ranks.select{ |job| job.reviews.job_id == params[:id] }

ER図

Image from Gyazo

参照

https://qiita.com/miyomiyo344/items/f75bd139bf644f9a6a36

乱雑な文申し訳ございません。
よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

Collection には job_id はありません。集合(みたいなもの)ですから。
その一つ一つにならあります。
つまりjob.reviews には ありませんが job.reviews.each{|review| の review にならあります。

投稿2022/11/17 11:42

winterboum

総合スコア23329

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

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

ddsky

2022/11/17 13:34

ご回答ありがとうございます。 以下のコードでエラーが出ます。 ``` @each_ranks = @all_ranks.reviews.each{ |review| review.job_id == params[:id] } ``` エラーメッセージ NoMethodError at /purpose_types/1 undefined method `reviews' for #<Array:0x00007f8b58dabd90> Did you mean? reverse @all_rankには複数配列データが入っているのでそのことが関係して今回のエラーが出ているのでしょうか。
ddsky

2022/11/17 13:36

以下、pry-railsで出たログです。 ``` [15] pry(#<PurposeTypesController>)> @all_ranks.each{|a|puts a} #<Job:0x00007f8b5bb00570> #<Job:0x00007f8b5bb00458> => [#<Job:0x00007f8b5bb00570 id: 1, name: "ハンバーガー屋", created_at: Wed, 16 Nov 2022 04:40:38 UTC +00:00, updated_at: Wed, 16 Nov 2022 04:40:38 UTC +00:00>, #<Job:0x00007f8b5bb00458 id: 2, name: "居酒屋", created_at: Wed, 16 Nov 2022 04:44:21 UTC +00:00, updated_at: Wed, 16 Nov 2022 04:44:21 UTC +00:00>] ```
winterboum

2022/11/17 14:06

>@all_rankには複数配列データが入っているのでそのことが関係して今回のエラーが出ているのでしょうか。 そうです。 データの集合は一つ一つ毎に処理しないと
ddsky

2022/11/17 15:15

@each_ranks = @all_ranks.reviews でNoMethodError が出ます。undefined method `reviews' for #<Array:0x00007f8b5bf22220> 何か参照の仕方が間違っていますか?
winterboum

2022/11/17 22:57

@all_ranks って rank の集合ですね? ですから rank のmethod reviews はありません @all_ranks.each{|rank| の rank にならあります。
winterboum

2022/11/17 22:58

@each_ranks = @all_ranks.select{ |job| job.reviews.job_id == params[:id] } は何をしたいのですか?
ddsky

2022/11/18 01:20 編集

@all_ranks = Job.find(Like.group(:job_id).order('count(job_id) desc').limit(10).pluck(:job_id)) @all_rankは機能としてはpurpose_type(カテゴリ)問わない全てのランキングですが、中身はJobの集合体です。 @each_ranksはそれぞれのpurposetypes#showページにていわばカテゴリ別のランキングを表示したいです。 params[:id]にはpurpose_typeの主キーであるidが格納されています。 以下の記事を参考にしています。 https://qiita.com/miyomiyo344/items/f75bd139bf644f9a6a36
winterboum

2022/11/18 01:24

Jobの集合体 がなぜ ランキング なのか とかが、このアプリ固有の定義なのでよくわからんです。 @each_ranks を カテゴリ別のランキング にしたいのですか?
ddsky

2022/11/18 03:43

おっしゃる通りです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問