PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Rails 4:l'utilizzo della funzione PostgreSQL nell'ordine provoca un errore nella query a causa della mancata unione della tabella include

Supponiamo di dover ottenere il nome utente dei primi cinque post. Scrivi rapidamente la domanda qui sotto e vai a goderti il ​​tuo fine settimana.

posts = Post.limit(5)

posts.each do |post|
  puts post.user.name
end

Bene. Ma diamo un'occhiata alle query

Post Load (0.5ms)  SELECT  `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 1 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 1 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 2 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 2 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 1 LIMIT 1

1 query per recuperare tutti i posts e 1 query per recuperare users per ogni post risulta un totale di 6 queries . Dai un'occhiata alla soluzione di seguito che fa la stessa cosa, solo in 2 queries :

posts = Post.includes(:user).limit(5)

posts.each do |post|
  puts post.user.name
end

#####

Post Load (0.3ms)  SELECT  `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2)

C'è una piccola differenza. Aggiungi includes(:posts) alla tua domanda e problema risolto. Veloce, piacevole e facile.

Ma non limitarti ad aggiungere includes nella tua query senza capirla correttamente. L'utilizzo di includes con joins potrebbe comportare collegamenti incrociati a seconda della situazione e nella maggior parte dei casi non è necessario.

Se vuoi aggiungere condizioni ai tuoi modelli inclusi, dovrai farne esplicito riferimento . Ad esempio:

User.includes(:posts).where('posts.name = ?', 'example')

Verrà generato un errore, ma funzionerà:

User.includes(:posts).where('posts.name = ?', 'example').references(:posts)

Nota che includes funziona con association names mentre references richiede the actual table name .