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

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

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

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

2回答

6671閲覧

N+1の問題に対するincludeやjoinで、リレーションモデルのその先のリレーションでN+1を解消するにはどうすればいいでしょうか?

kento2543

総合スコア163

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

1グッド

2クリップ

投稿2016/05/29 05:46

次のような例の場合で、postに対するcategoryがN+1の問題が生じてしまいます。
こういうケースにおいて、joinなりincludeなどで解消することはできないのでしょうか?

Userに対してはpostのincludeはできますが、categoryに対してはできませんでした。

設計から見直す必要があるのでしょうか?

よろしくお願いします。

controller

class UserController < ApplicationController @users = User.all.include(:posts) end

view

- @users.each do |user| - user.posts.each do |post| = post.name = post.category.name <==こういうの = post.like_count

modelのリレーション

User.has_many :posts Post.has_one :category Post.belongs_to :user Category.belongs_to :post
gesorein👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

Ruby

1@user = User.includes(posts: :category).all

で行けませんか?

投稿2016/05/29 11:31

rifuch

総合スコア1901

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

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

kento2543

2016/05/29 11:47

ご回答ありがとうございます。 こういう記法でできるんですね。 なかなか参照できる記事が見つからなかったので、大変勉強になりました。 今回の用件上、さらにネストしたリレーションがありまして、 次のようなケースです。 Category.belongs_to :book Booka.has_one :category - @users.each do |user| - user.posts.each do |post| post.category.book <==こういうケース この場合もN+1が発生してしまうため何とかしたいです。 よろしくお願いします。
kento2543

2016/05/29 12:08

↑のようなケース色々と試していると .includes(posts: { category: :book } ) でできました。 しかし、こういうやり方をcontrollerに書くのがセオリーなんでしょうか・・・。 また、こういうのをもし調べようと思った際に、どういうキーワードで検索したらでますでしょうか?(Railasではこいうのを何と表現しているのかを知りたいです。)
rifuch

2016/05/29 12:56

返答が遅れてすみません。 ちなみに、 user has_many :posts user has_many :favorites post has_one :category favorite has_many :comments みたいなモデルがあったとしたら、 User.includes([posts: :category, favorites: :comments]).all みたいな書き方も出来ます。 コントローラーに書くか、モデルに書くかですが、ここはケースバイケースでしょう。 常にn+1問題が発生するような検索をする場合は、 modelのhas_many等に:includesオプションをつけてやれば、常にeager_loadingしてくれます。 この辺は、Railsガイド(http://railsguides.jp/association_basics.html)のアソシエーションの項目に出てきます。 検索するなら、eager_loading, includes, joinsあたりがキーワードになるでしょうか。
kento2543

2016/05/30 03:59

コントローラーに書くか、モデルに書くかですが、ここはケースバイケースなんですね。 まだ、私は経験不足なので、ひとまず、Controller毎に書こうとおもいます。 includesの記法も、まだまだ、勉強不足だったので、大変参考になりました! ありがとうございます!
guest

0

コントローラのアクション内で

@users = User.all
@posts = @users.posts.includes(:category)

でうまくいきませんか?

投稿2016/05/29 07:03

realizerS

総合スコア265

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

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

kento2543

2016/05/29 07:08

ありがとうございます。 しかしそれをすると今度はUserがN+1を起こすと思います。 仮に @users = User.include(:posts) としても、 view側では次のようなループを回したいため、今回のようなやり方では実現できないのかなと思いました。私自身も勉強不足ですので、思っているのと違ってましたらすみません。 - @users.each do |user| - user.posts.each do |post| = post.name = post.category.name <==こういうの = post.like_count
kento2543

2016/05/29 07:10

また、今回はリレーションを必要なものだけ取り出しましたが、 実際にはUserには他のリレーションもincludeしていたりしています。
realizerS

2016/05/29 07:21 編集

あ、なんか勘違いしていました。すみません。 修正。 @users = User.all @posts = Post.all.includes(:category) でいけませんか? 追伸) 確認は`bullet`のgemがおすすめです
kento2543

2016/05/29 08:01 編集

`bullet`のgemはいれてます! @posts = Post.all.includes(:category) ですと、view側ではどういうしょりになるのでしょうか? こういうのはできないのではないかと思います。 - @users.each do |user| - user.posts.each do |post| @usersでループを回しのuser毎のpostsを取得したいのですが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問