Lebih baik:
Person.includes(:friends).where( :friends => { :person_id => nil } )
Untuk hmt pada dasarnya hal yang sama, Anda bergantung pada kenyataan bahwa seseorang tanpa teman juga tidak akan memiliki kontak:
Person.includes(:contacts).where( :contacts => { :person_id => nil } )
Memperbarui
Punya pertanyaan tentang has_one
di komentar, jadi baru saja memperbarui. Kuncinya di sini adalah bahwa includes()
mengharapkan nama asosiasi tetapi where
mengharapkan nama tabel. Untuk suatu has_one
asosiasi umumnya akan diekspresikan dalam bentuk tunggal, sehingga berubah, tetapi where()
bagian tetap seperti itu. Jadi, jika Person
hanya satu has_one :contact
maka pernyataan Anda adalah:
Person.includes(:contact).where( :contacts => { :person_id => nil } )
Perbarui 2
Seseorang bertanya tentang kebalikannya, teman tanpa orang. Seperti yang saya komentari di bawah ini, ini benar-benar membuat saya menyadari bahwa bidang terakhir (di atas: the :person_id
) tidak benar-benar harus terkait dengan model yang Anda kembalikan, hanya harus berupa bidang di tabel bergabung. Mereka semua akan nil
jadi bisa salah satu dari mereka. Ini mengarah ke solusi yang lebih sederhana untuk yang di atas:
Person.includes(:contacts).where( :contacts => { :id => nil } )
Dan kemudian beralih ini untuk mengembalikan teman tanpa orang menjadi lebih sederhana, Anda hanya mengubah kelas di depan:
Friend.includes(:contacts).where( :contacts => { :id => nil } )
Perbarui 3 - Rel 5
Terima kasih kepada @Anson untuk solusi Rails 5 yang sangat baik (beri dia +1 untuk jawabannya di bawah), Anda dapat menggunakan left_outer_joins
untuk menghindari memuat asosiasi:
Person.left_outer_joins(:contacts).where( contacts: { id: nil } )
Saya sudah memasukkannya di sini sehingga orang-orang akan menemukannya, tetapi dia layak mendapatkan +1 untuk ini. Tambahan yang bagus!
Pembaruan 4 - Rel 6.1
Terima kasih kepada Tim Park karena telah menunjukkan bahwa pada 6.1 mendatang Anda dapat melakukan ini:
Person.where.missing(:contacts)
Berkat pos yang dia tautkan juga.