PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Rails 4 :L'utilisation de la fonction PostgreSQL dans l'ordre provoque une erreur dans la requête car la table include n'est pas jointe

Supposons que vous ayez besoin d'obtenir le nom d'utilisateur des cinq premiers messages. Vous écrivez rapidement la requête ci-dessous et allez profiter de votre week-end.

posts = Post.limit(5)

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

Bien. Mais regardons les requêtes

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 pour récupérer tous les posts et 1 query pour récupérer les users pour chaque message, cela donne un total de 6 queries . Découvrez la solution ci-dessous qui fait la même chose, juste en 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)

Il y a une petite différence. Ajouter includes(:posts) à votre requête, et problème résolu. Rapide, agréable et facile.

Mais ne vous contentez pas d'ajouter includes dans votre requête sans bien la comprendre. Utiliser includes avec joins peut entraîner des jointures croisées selon la situation, et vous n'en avez pas besoin dans la plupart des cas.

Si vous souhaitez ajouter des conditions à vos modèles inclus, vous devrez les référencer explicitement . Par exemple :

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

Lancera une erreur, mais cela fonctionnera :

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

Notez que includes fonctionne avec les association names tandis que les references nécessite the actual table name .