題材: left_joins とかして重複した結果をユニークにするには uniq じゃなくて distinct が良いよ!
ユーザーが10人いるとき
User.count
# => 10
ユーザーがそれぞれ本を何冊も持ってると、結果が増えるよね!
User.left_joins(:books).size
# => 30
結果を uniq したら、ユーザーはユニークになるけど?
User.left_joins(:books).uniq.size
# => 10
アソシエーションが途切れてしまうので、その後に ActiveRecord 関係のメソッドを繋げられなくなるよ!
User.left_joins(:books).uniq.where(id: 1)
# NoMethodError: undefined method `where'
Kaminari gem のページングするときとかに困るよね?
User.left_joins(:books).uniq.page(1)
# NoMethodError: undefined method `page'
でも distinct なら問題ないね!
User.left_joins(:books).distinct.size
# => 10
User.left_joins(:books).distinct.where(id: 1)
User.left_joins(:books).distinct.page(1)
この場合の distinct は uniq と結果自体は同じだよ
同じインスタンスの配列が返ってきているよ
User.left_joins(:books).distinct == User.left_joins(:books).uniq
# true
distinct で何が起きているかは SQL を見てみよう!
User.left_joins(:books).to_sql
# => "SELECT `users`.* FROM `users` LEFT OUTER JOIN `books` ON `books`.`user_id` = `users`.`id`"
User.left_joins(:books).distinct.to_sql
# => "SELECT DISTINCT `users`.* FROM `users` LEFT OUTER JOIN `books` ON `books`.`user_id` = `users`.`id`"
uniq は Ruby のメソッドなので、メソッドチェーン先の to_sql メソッドはないよ。
User.left_joins(:books).uniq.to_sql
# NoMethodError: undefined method `to_sql' for #<Array:0x000055b59ea9cbb8>
User.left_joins(:books).uniq.class
# Array
Original by Github issue
チャットメンバー募集
何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。