🖥

#Rails 初心者向け - ActiveRecord のメソッドとRubyメソッドの違いを意識してみる

2019/07/03に公開

題材: 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

https://github.com/YumaInaura/YumaInaura/issues/2235

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

Twitter

https://twitter.com/YumaInaura

公開日時

2019-07-03

Discussion