Besser:
Person.includes(:friends).where( :friends => { :person_id => nil } )
Für das hmt ist es im Grunde dasselbe, Sie verlassen sich auf die Tatsache, dass eine Person ohne Freunde auch keine Kontakte hat:
Person.includes(:contacts).where( :contacts => { :person_id => nil } )
Aktualisieren
Ich habe eine Frage zu has_one
in den Kommentaren, also nur aktualisieren. Der Trick dabei ist, includes()
dass der Name der Zuordnung where
erwartet wird, aber der Name der Tabelle. Für a wird has_one
die Assoziation im Allgemeinen im Singular ausgedrückt, so dass sich dies ändert, aber der where()
Teil bleibt wie er ist. Wenn also Person
nur has_one :contact
dann Ihre Aussage wäre:
Person.includes(:contact).where( :contacts => { :person_id => nil } )
Update 2
Jemand fragte nach dem Gegenteil, Freunde ohne Menschen. Wie ich unten kommentierte, wurde mir tatsächlich klar, dass das letzte Feld (oben: das :person_id
) nicht unbedingt mit dem Modell verknüpft sein muss, das Sie zurückgeben, sondern nur ein Feld in der Verknüpfungstabelle. Sie werden alle nil
so sein, dass es jeder von ihnen sein kann. Dies führt zu einer einfacheren Lösung für das oben Gesagte:
Person.includes(:contacts).where( :contacts => { :id => nil } )
Und dann wird es noch einfacher, dies zu ändern, um die Freunde ohne Personen zurückzugeben. Sie ändern nur die Klasse an der Vorderseite:
Friend.includes(:contacts).where( :contacts => { :id => nil } )
Update 3 - Schienen 5
Dank @Anson für die hervorragende Rails 5-Lösung (geben Sie ihm einige +1 für seine Antwort unten) können Sie das left_outer_joins
Laden der Assoziation vermeiden:
Person.left_outer_joins(:contacts).where( contacts: { id: nil } )
Ich habe es hier aufgenommen, damit die Leute es finden, aber er verdient die +1 dafür. Tolle Ergänzung!
Update 4 - Rails 6.1
Vielen Dank an Tim Park für den Hinweis, dass Sie dies in der kommenden Version 6.1 tun können:
Person.where.missing(:contacts)
Dank des Beitrags, auf den er auch verlinkt hat.