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

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

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

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

Ruby on Rails

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

Q&A

解決済

1回答

3338閲覧

【Ruby on Rails】多対多のアソシエーションに別名を使いたいのですが、上手くいきません

kumamin

総合スコア12

Ruby

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

Ruby on Rails

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

1グッド

0クリップ

投稿2020/09/09 02:25

前提・実現したいこと

今、CtoCで旅行の案内ができる人と案内してほしい人をマッチングさせるアプリを制作しておりまして、
旅行の案内をする人をツアーキャスト、旅行の案内を受ける人をツアーゲストと定義しています。

そしてツアーキャスト、ツアーゲスト両方とも投稿することができ、
その投稿に対しては複数のユーザーが申し込むことができるように実装したいです。

ここでは、ツアーキャストとしての投稿のモデルをPostC、ツアーゲストとしての投稿のモデルをPostGとしています。
また、その投稿を申し込む人のことをtakerと定義し、takerは複数人いても良いのでPostCtakerは多対多の関係とします。
PostGtakerの関係も同様です。
さらに、申し込み済みのツアーキャストの投稿をtaking_post_cs、ツアーゲストの投稿をtaking_post_gsと定義しています。

ユーザーのマイページで、そのユーザーが申し込んだ投稿を一覧で見られるようにしたいのですが、
エラーが表示されてしまうので、解決法を教えていただけると助かります。

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

ActiveRecord::HasManyThroughSourceAssociationNotFoundError in UsersController#show Could not find the source association(s) :post_g in model PostGTaker. Try 'has_many :taking_post_gs, :through => :post_g_takers, :source => <name>'. Is it one of taking_post_g or taker?

イメージ説明

該当のソースコード

▼models/user.rb

Ruby

1class User < ApplicationRecord 2 3 has_many :post_g_takers 4 has_many :taking_post_gs, through: :post_g_takers, source: :post_g 5 has_many :post_c_takers 6 has_many :taking_post_cs, through: :post_c_takers, source: :post_c 7 8end

▼models/post_g.rb

Ruby

1class PostG < ApplicationRecord 2 has_many :post_g_takers 3 has_many :takers, through: :post_g_takers 4end

▼models/post_g_taker.rb

Ruby

1class PostGTaker < ApplicationRecord 2 belongs_to :taking_post_g, class_name: 'PostG', foreign_key: 'taker_id' 3 belongs_to :taker, class_name: 'User', foreign_key: 'taker_id' 4end

▼users_controller.rb

Ruby

1class UsersController < ApplicationController 2 3 def show 4 @user = User.find(params[:id]) 5 @taking_post_gs = @user.taking_post_gs 6 @taking_post_cs = @user.taking_post_cs 7 end 8 9end

▼views/users/show.html.haml

haml

1.Title 2 = "#{@user.name}さんのページ" 3 4.User_page_tabs 5 - if user_signed_in? && @user.id == current_user.id 6 = link_to "申込済み(ツアーゲスト)", "#", class: "User_page_tab" 7 = link_to "申込済み(ツアーキャスト)", "#", class: "User_page_tab" 8 9.User_posts 10 - if @taking_post_gs.empty? 11 .Empty 投稿がありません 12 - else 13 .Post_index 14 - @taking_post_gs.each do |post| 15 = render partial: "posts_g/post", locals: { post: post } 16.User_posts 17 - if @taking_post_cs.empty? 18 .Empty 投稿がありません 19 - else 20 .Post_index 21 - @taking_post_cs.each do |post| 22 = render partial: "posts_c/post", locals: { post: post }

▼schema.rb

Ruby

1ActiveRecord::Schema.define(version: 2020_09_08_123347) do 2 3 create_table "post_c_takers", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 4 t.bigint "post_c_id" 5 t.bigint "taker_id" 6 t.datetime "created_at", precision: 6, null: false 7 t.datetime "updated_at", precision: 6, null: false 8 t.index ["post_c_id"], name: "index_post_c_takers_on_post_c_id" 9 t.index ["taker_id"], name: "index_post_c_takers_on_taker_id" 10 end 11 12 create_table "post_cs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 13 t.string "region", null: false 14 t.string "datetime", null: false 15 t.text "content", null: false 16 t.string "charge", null: false 17 t.bigint "giver_id", null: false 18 t.datetime "created_at", precision: 6, null: false 19 t.datetime "updated_at", precision: 6, null: false 20 t.string "title", null: false 21 t.string "payment", null: false 22 t.string "image" 23 t.index ["giver_id"], name: "index_post_cs_on_giver_id" 24 t.index ["region"], name: "index_post_cs_on_region" 25 end 26 27 create_table "post_g_takers", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 28 t.bigint "post_g_id" 29 t.bigint "taker_id" 30 t.datetime "created_at", precision: 6, null: false 31 t.datetime "updated_at", precision: 6, null: false 32 t.index ["post_g_id"], name: "index_post_g_takers_on_post_g_id" 33 t.index ["taker_id"], name: "index_post_g_takers_on_taker_id" 34 end 35 36 create_table "post_gs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 37 t.string "region", null: false 38 t.string "datetime", null: false 39 t.text "content", null: false 40 t.string "charge", null: false 41 t.bigint "giver_id", null: false 42 t.datetime "created_at", precision: 6, null: false 43 t.datetime "updated_at", precision: 6, null: false 44 t.string "title", null: false 45 t.string "payment", null: false 46 t.string "image" 47 t.index ["giver_id"], name: "index_post_gs_on_giver_id" 48 t.index ["region"], name: "index_post_gs_on_region" 49 end 50 51 create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 52 t.string "name", null: false 53 t.string "email", default: "", null: false 54 t.string "encrypted_password", default: "", null: false 55 t.text "profile" 56 t.string "profile_image" 57 t.string "reset_password_token" 58 t.datetime "reset_password_sent_at" 59 t.datetime "remember_created_at" 60 t.datetime "created_at", precision: 6, null: false 61 t.datetime "updated_at", precision: 6, null: false 62 t.index ["email"], name: "index_users_on_email", unique: true 63 t.index ["name"], name: "index_users_on_name", unique: true 64 t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true 65 end 66 67 add_foreign_key "post_c_takers", "post_cs" 68 add_foreign_key "post_c_takers", "users", column: "taker_id" 69 add_foreign_key "post_cs", "users", column: "giver_id" 70 add_foreign_key "post_g_takers", "post_gs" 71 add_foreign_key "post_g_takers", "users", column: "taker_id" 72end

試したこと

user.rbのsourceの部分をsource: :taking_post_gにしてみたところ、別のエラーが出ました。
イメージ説明
しかし、以下のサイトを見てsourceは実在するモデル名ではないといけないのでは?と思い、上記にはpost_gと書いたコードを載せました。
https://kimuraysp.hatenablog.com/entry/2017/09/05/235816

necocoa👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

1.source

user.rbsource: :taking_post_gこちらで合っています。
sourceにはthroughした先のModelに紐付いている値を指定します。
つまり、今回の場合はtakertaking_post_gになります。

ruby

1class PostGTaker < ApplicationRecord 2 belongs_to :taking_post_g, class_name: 'PostG', foreign_key: 'taker_id' 3 belongs_to :taker, class_name: 'User', foreign_key: 'taker_id' 4end
2.foreign_key

▼models/post_g_taker.rb

ruby

1class PostGTaker < ApplicationRecord 2 belongs_to :taking_post_g, class_name: 'PostG', foreign_key: 'taker_id' 3 belongs_to :taker, class_name: 'User', foreign_key: 'taker_id' 4end

この部分のforeign_keyはpost_g_idではないですか?
belongs_to :taking_post_g, class_name: 'PostG', foreign_key: 'taker_id'
taking_post_gとtaker、どちらもforeign_keyがtaker_idになっています。

上記2つを修正すると今回出ていたエラーを解消できるかと思います。
試してみてください!

投稿2020/09/09 02:48

necocoa

総合スコア209

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

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

kumamin

2020/09/09 03:02

早速のご回答、ありがとうございます! sourceについて、taking_post_gで合ってたんですね。勉強になりました。 また、`belongs_to :taking_post_g, class_name: 'PostG', foreign_key: 'taker_id'`の foreign_keyの部分を`post_g_id`と変更してみたのですが、 質問に載せた2枚目の画像と全く同じエラー画面が表示されてしまいました。
necocoa

2020/09/09 03:25

2枚目の画像のエラーを見てみると3行目の Mysql2::Error: Unknown column 'post_g_takers.user_id' と書いてあります。 post_g_takersには`taker_id`と`post_g_id `がカラムとして存在するのでuser_idは無いのがわかります。 これからわかるのが、@user.post_g_takers を実行した時にuser_idを探しているのがわかります。 よって、今回漏れていたのが user.rbの`has_many :post_g_takers`にforeign_keyの指定でtaker_idを指定するとうまくいきそうです。 質問の最後に貼ってあった参照サイトを見ながらやれば解決できそうです。 試してみてください!
kumamin

2020/09/09 04:25

おかげさまで、無事解決できました! 迅速かつ大変丁寧なご回答をしていただき、本当に助かりました。 ありがとうございました!!
necocoa

2020/09/09 04:30

解決できてよかったです!これからもファイトです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問