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

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

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

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

Ruby on Rails 6

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

1回答

4365閲覧

[Ruby on Rails]多段階にネストされたモデルをincludesで取得する際の書き方について

yomigi

総合スコア43

Ruby

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

Ruby on Rails 6

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2020/10/22 11:05

編集2020/10/22 13:48
  • Roomテーブル
IDname
1room1
  • Userテーブル
IDroom_idname
11ユーザ1
21ユーザ2
  • Postテーブル
IDroom_iduser_idname
111post1
212post2
  • Commentテーブル
IDroom_iduser_idpost_idmessage
1111comment1
2111comment2
3122comment3
  • Assetテーブル
IDroom_iduser_idpost_idcomment_idasset_typefile_path
1111nullimageXXX/YYY
212nullnullimageXXX/YYY
31112imageXXX/YYY
41223imageXXX/YYY
51223movieXXX/YYY
class Room < ApplicationRecord has_many :users end class User < ApplicationRecord belongs_to :room has_many :posts has_many :images, -> { where(asset_type: "image") }, class_name: "Asset" has_many :movies, -> { where(asset_type: "movie") }, class_name: "Asset" end class Post < ApplicationRecord belongs_to :user has_many :comments has_many :images, -> { where(asset_type: "image") }, class_name: "Asset" has_many :movies, -> { where(asset_type: "movie") }, class_name: "Asset" end class Comment < ApplicationRecord belongs_to :post has_many :images, -> { where(asset_type: "image") }, class_name: "Asset" has_many :movies, -> { where(asset_type: "movie") }, class_name: "Asset" end class Asset < ApplicationRecord enum asset_type: { image: "image", movie: "movie" } end

上記のような関連付けを持ったRailsアプリケーションを作成しております。
日本語で簡単に書くと以下のようになります。

  • Roomは複数のUserをもつ
  • Userは複数のPost、及び複数のimageとmovieをもつ
  • Postは複数のComment、及び複数のimageとmovieをもつ
  • Commentは複数のimageとmovieをもつ
  • Asset(imageとmovieの実体)はUserとPostとCommentに紐づく

各モデルには外部キーとして所属するモデルのIDを持っているとさせてください。
例:Userモデルにはroom_idがあり、Assetモデルにはuser_idとpost_idとcomment_idがある・・という状況

ここで質問の本題となるのですが、

あるRoomに紐づく上記全ての情報をなるべく少ないSQLの発行回数となるようincludesを用いて所得する

にはどのように書けば良いのでしょうか。

なんとなく以下のような実装になるのかなと考えているのですが、、これでは足りていない認識です。

room_id = 1 # 一例 Room.find_by(id: room_id).users.includes(posts: {comments: [:movies, :images]})

追記:
includesで、と書いてしまいましたが、
上記内容(少ないSQLで関連テーブルの情報を合わせて取得する)が達成できれば
どんな方法でも構いません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

それだと得られるのはusersでroomではない  のでは?

Roomは複数のUserをもつ
Userは複数のPost、及び複数のimageとmovieをもつ
Postは複数のComment、及び複数のimageとmovieをもつ
Commentは複数のimageとmovieをもつ

Room.includes(users: [:images, :movies, posts: [:movies,:images, comments: [:movies,:images] ] ] ).find(room_id)
かな?
「Asset(imageとmovieの実体)はUserとPostとCommentに紐づく」
ここは関連定義、Asset、imageとmovie の定義 が載ってないのでイメージ湧きません。(うすうすはわかるけど、推定で書くとおかしなことになるかも、だから)

追記
出来るかどうか、、、
データ例をみると 必ず roomには属するみたいですから,この関係付けも宣言し、Assetからuser,post,commentへの関連も定義して
assets = Asset.includes(:room,:users,:posts,:comments)
(もしかしたら Asset.includes(:users,:posts,:comments,room: {users: {posts: :comments}) かも、、、)
したあと、
assets.map(&:rooms).uniq
Arrayになってしまいますが。
Asset.includes(。。).room でassetsが取れるなんてことないだろうなぁ、、、

投稿2020/10/22 12:46

編集2020/10/22 22:37
winterboum

総合スコア23567

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

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

yomigi

2020/10/22 13:13

失礼しました! 私の説明文に誤りがありましたので修正させていただきました。 >ここは関連定義、Asset、imageとmovie の定義 が載ってないのでイメージ湧きません。 こちらですが、Assetテーブルにuser_id,post_id,comment_idを持っており、かつAsset.asset_typeというカラムがある状況となります。 >それだと得られるのはusersでroomではない  のでは? こちらはその通りですね。。失礼しました。ご指摘いただきありがとうございます。 追加の質問となってしまうのですが、 いただいたコメントにある実装だと 計6回Assetテーブルに対してselectが走ってしまうかと思うのですが、 これはもう仕方がない感じでしょうか・・? (提示している情報に不足があるための結果でしたら申し訳ありません)
winterboum

2020/10/22 13:16

そういうややこしい設計の場合は、modelと関連定義を拝見しないとわかりません
yomigi

2020/10/22 13:49

お手数おかけいたします、、テーブル構成を追加いたしました。 こちらで足りれば良いのですが・・
winterboum

2020/10/22 21:15

テーブルのデータをみると一つのAssetが復数のmodelにbelongstoするわけですね。 ふーむ、、、 追記に書きますが、こんなのではどうかな。。。
yomigi

2020/10/23 08:21 編集

追記いただきありがとうございます! いただいた方法で目的の結果は得ることができましたのでBAとさせていただきました。 長々とお付き合いいただいてしまってすみません。。 (なんとなく、元々の設計が複雑すぎたのかなあ・・という印象ではあります。。)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問