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

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

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

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

Ruby

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

Q&A

解決済

2回答

1195閲覧

テーブル内に該当するレコードが存在するかどうかを確認したい

zin2

総合スコア21

Ruby on Rails 5

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

Ruby

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

0グッド

0クリップ

投稿2018/10/09 13:30

編集2018/10/10 01:21

中間テーブルを介したhas_manyな関係にあるテーブルに、該当するレコードが存在するかを確認したい

作ったコードがスマートではないため、もっと良いコードがあれば教えてください。

前提条件

model

1class Account < ApplicationRecord 2 has_many :group_accounts 3end 4 5class GroupAccount < ApplicationRecord 6 belongs_to :group 7 belongs_to :account 8end 9 10class Group < ApplicationRecord 11has_many :group_accounts 12end

table

1class CreateGroups < ActiveRecord::Migration[5.1] 2 def change 3 create_table :groups do |t| 4 t.string :team_name 5 t.timestamps 6 end 7 end 8end 9 10class CreateGroupAccounts < ActiveRecord::Migration[5.1] 11 def change 12 create_table :group_accounts do |t| 13 t.integer :group_id 14 t.integer :account_id 15 t.string :join_switch 16 t.timestamps 17 end 18 end 19end 20 21class CreateAccounts < ActiveRecord::Migration[5.1] 22 def change 23 create_table :users do |t| 24 t.string :name 25 t.timestamps 26 end 27 end 28end

作ったコード

Ruby

1<% @switch_true=[] %> 2 3<% Groups.each do |group| %> 4 <% @pickup_group_accounts = group.group_accounts.where('account_id = ?', current_account.id).where('join_switch = ?', "true") %> 5 <% if @pickup_group_accounts.present? %> 6  <% @switch_true.push @pickup_group_accounts %> 7 <% end %> 8<% end %> 9 10<% if @switch_true.present? %> 11 参加者あり 12<% else %> 13 参加者なし 14<% end %>

ご説明と解決方法の検討(自己検討)

Groupテーブルからレコードを順番に取り出し、Groupに紐づいた中間テーブル(group_accounts)で検索条件を指定し、さらにAccountsテーブルで検索条件を指定した上で、該当レコードを抽出しています。

テーブル同士がhas_manyな関係にあるため、eachメソッドのループ内で

Ruby

1<% Groups.each do |group| %> 2 <% @pickup_group_accounts = group.group_accounts.where('account_id = ?', current_account.id).where('join_switch = ?', "true") %> 3 <% if @pickup_group_accounts.present? %> 4  参加者あり 5 <% else %> 6  参加者なし 7 <% end %> 8<% end %>

というやり方をすると、重複した結果(参加者あり)が複数取り出されてしまいましたので、上記の方法で判別していますが、力技っぽくていまいちな印象を持っています。

なんとなくjoinメソッドを使えば上手く取り出せそうな感じがしましたが、どうすれば良いか思いつかず、詰まってしまいました。
どなたかご教授いただけませんでしょうか?

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

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

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

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

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

guest

回答2

0

ベストアンサー

書き方もそうですがSQL発行回数も意識すると良いでしょう
グループごとにチェックを行うと Group.each の1回と、グループ数のN回のSQLが発行されます
N+1と言われる問題で、グループが増えたびに遅くなる問題を抱えています

■条件付きの has_many を定義がお勧め

表示時に条件を書かずに比較的スッキリするしSQL発行回数もpreloadを使えるためGroupが増えても2回です

ruby

1class Group < ApplicationRecord 2 has_many :group_accounts 3 has_many :joined_group_accounts, -> { where(join_switch: "true") }, class_name: 'GroupAccount' 4end 5 6<% Group.preload(:joined_group_accounts).each do |group| %> 7 <% if group.joined_group_accounts.map(&:account_id).include?(current_account.id) %> 8  参加者あり 9 <% else %> 10  参加者なし 11 <% end %> 12<% end %>

■ has_many through もお勧め

中間テーブルを意識しなくて良くなります

ruby

1class Group < ApplicationRecord 2 has_many :group_accounts 3 has_many :joined_group_accounts, -> { where(join_switch: "true") }, class_name: 'GroupAccount' 4 has_many :joined_accounts, through: :joined_group_accounts, source: :account 5end 6 7<% Group.preload(:joined_accounts).each do |group| %> 8 <% if group.joined_accounts.include?(current_account) %> 9  参加者あり 10 <% else %> 11  参加者なし 12 <% end %> 13<% end %>

投稿2018/10/11 08:13

編集2018/10/11 08:15
Ighrs

総合スコア656

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

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

zin2

2018/10/11 10:31

ありがとうございました! 全く知らなかった方法でしたので、大変勉強になりました。 N+1問題については、ずっと引っかかっていましたが、解決できました!
guest

0

Ruby

1<% if Groups.joins(:group_accounts).where(group_accounts: {account_id: current_account.id}).where(group_accounts: {join_switch: "true"}).present? %> 2  参加者あり 3 <% else %> 4  参加者なし 5 <% end %> 6<% end %> 7

でいけないかと思いましたが、上手く取り出せませんでした。

投稿2018/10/10 00:29

編集2018/10/10 01:22
zin2

総合スコア21

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問