che sto utilizzando il metodo AR includes
per eseguire un join esterno sinistro tra gli oggetti utente e costruzione, dove un utente può o non può avere un'associazione di costruzione:comportamento imprevisto con ActiveRecord comprende
users = User.includes(:building).references(:buildings)
Dato che sto usando references
, qualsiasi oggetto Building associato sarà caricato con entusiasmo.
La mia aspettativa era che sarei stato in grado di scorrere l'elenco degli utenti e controllare se un utente aveva un edificio associato con loro senza attivare query aggiuntive, ma vedo che in effetti ogni volta che provo ad accedere all'edificio proprietà di un utente che non ne ha uno, AR effettua un'altra chiamata SQL per provare a recuperare tale edificio (anche se nei tentativi successivi restituirà solo zero).
Queste query sono ovviamente ridondanti in quanto l'associazione sarebbe stata caricata durante il join iniziale e sembra vanificare l'intero scopo del caricamento ansioso con include/riferimenti, poiché ora sto osservando N volte il numero di query uguali al numero di associazioni vuote.
users.each do | user |
# This will trigger a new query when building is not present:
# SELECT "buildings".* FROM "buildings" WHERE "buildings"."address" = $1 LIMIT 1 [["address", "123 my street"]]
if user.building
puts 'User has building'
else
puts 'User has no building'
end
end
classe User:
class User < ActiveRecord::Base
belongs_to :building, foreign_key: 'residence_id'
end
C'è un modo per verificare la presenza di un'associazione costruzione degli utenti senza innescare query in più?
On Rails 4.2.0/POSTGRES
UPDATE:
Grazie @BoraMa per mettere insieme questo test. Sembra che stiamo ottenendo un comportamento differente tra le versioni Rotaie recenti:
USCITA (rotaie 4.2.0):
User 1 has building
User 2 has building
User 3 has no building
D, [2016-05-26T11:48:38.147316 #11910] DEBUG -- : Building Load (0.2ms) SELECT "buildings".* FROM "buildings" WHERE "buildings"."id" = $1 LIMIT 1 [["id", 123]]
User 4 has no building
USCITA (rotaie 4.2.6)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
USCITA (rotaie 5.0 .0)
User 1 has building
User 2 has building
User 3 has no building
User 4 has no building
rosticcerie:
- Questo problema è stato limitato a "penzolanti chiavi esterne (cioè la colonna residence_id non è nullo, ma non corrisponde alcun oggetto edificio)" (Grazie @FrederickCheung)
- Il problema è stato risolto alla Rails 4.2. 6
Mi aspetterei un errore simile a "ActiveRecord :: AssociationNotFoundError: associazione denominata" edifici "non trovata sull'utente". Puoi confermare la sintassi della query e User-> Building association definition? – messanjah
@messanjah Personalmente mi aspetterei che 'user.building' restituisca nil se l'associazione non esiste, e questo è ciò che succede nelle chiamate successive, ma alla prima chiamata spara sempre una query SQL. – Yarin
Strano, non osservo questo comportamento - le mie associazioni nil stanno tornando a zero, senza ulteriori domande. Il codice che hai fornito nella domanda è davvero un esempio operativo minimo del problema? – BoraMa