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

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

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

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

Ruby

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

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

1回答

1214閲覧

【Rails5】リレーション先を含めたor検索について

ssk

総合スコア332

Ruby on Rails 5

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

Ruby

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

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

3クリップ

投稿2019/07/07 06:35

やりたいこと

中間テーブルを含めた検索をかけたいです。
なんとか実装までは漕ぎ着けたんですが、他に良い方法(または間違っているなど)など、ご指摘いただると幸いです。

試していること

ruby

1def index 2# events_controller.rb 3 scope = Event.includes(:users, :creator, :updater) 4 scope = scope.select { |e| (e.publish? or e.joins?(current_user)) } 5 scope = Event.revive_active_record(scope) 6 7 # ここから検索条件 8 @q = scope.ransack(params[:q]) 9101112end

ruby

1# event.rb 2has_many :attendee_events, dependent: :destroy 3has_many :users, through: :attendee_events 4 5def joins?(user) 6 users.exists?(user.id) 7end 8 9def self.revive_active_record(arr) 10 arr.first.class.where(id: arr.map(&:id)) 11end

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

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

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

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

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

gentaro

2019/07/07 15:59

間違っているのかどうかは自分で動かせば(テストすれば)わかるはずです。 他に方法があるのか、という漠然とした質問は基本的にナシだと思います。(あなたが何を持って「良い」とするのか、誰もわからない) とりあえず↓読んで質問のやり方を変えましょう。 https://teratail.com/help/question-tips https://teratail.com/help/avoid-asking
guest

回答1

0

ベストアンサー

100件あると e.joins?(current_user) が 100回動いて100回SQLが発行されませんか?
N+1と呼ばれる問題で、データが増えるたびにどんどん遅くなるので危険です
またページングまで考慮すると最初の20件だけ取る場合でも全件チェックしているのも効率が悪いです

ruby

1# 逆向きにUserから参照できるようにしておきます 2class User 3 has_many :attendee_events 4 has_many :events, through: :attendee_events 5end

ruby

1def index 2 # 同じモデルのリレーションなら where.or が使えます 3 scope = Event.publish.where.or(current_user.events) 4 5 # or の部分には includes はいらないのでこちらにつければ十分だと思われます 6 scope = Event.includes(:users, :creator, :updater) 7 .revive_active_record(scope) 8end

ruby

1 2# 1. 条件を追加する場合はクラス関数ではなく scope をオススメ、 whereで繋がります 3# 2. 引数を配列ではなくRelationにできたので select(:id) オススメ、全件抽出せずサブクエリで指定できます 4# 3. ここまで短くなればそもそも分離しなくて良いかもですね 5scope :revive_active_record, ->(relation) do 6 where(id: relation.select(:id)) 7end 8

投稿2019/07/10 09:36

編集2019/07/10 20:53
Ighrs

総合スコア656

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問