PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Rails 4:Usar a função PostgreSQL em ordem causa erro na consulta devido à tabela de inclusão não ser unida


Suponha que você precise obter o nome de usuário dos cinco primeiros posts. Você escreve rapidamente a consulta abaixo e vai curtir seu final de semana.
posts = Post.limit(5)

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

Bom. Mas vamos ver as consultas
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 para buscar todos os posts e 1 query para buscar users para cada postagem resulta em um total de 6 queries . Confira a solução abaixo que faz a mesma coisa, apenas em 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)

Há uma pequena diferença. Adicione includes(:posts) para sua consulta e problema resolvido. Rápido, bonito e fácil.

Mas não basta adicionar includes em sua consulta sem entendê-la corretamente. Usando includes com joins pode resultar em junções cruzadas, dependendo da situação, e você não precisa disso na maioria dos casos.

Se você quiser adicionar condições aos seus modelos incluídos, precisará referenciá-los explicitamente . Por exemplo:
User.includes(:posts).where('posts.name = ?', 'example')

Irá lançar um erro, mas isso funcionará:
User.includes(:posts).where('posts.name = ?', 'example').references(:posts)

Observe que includes funciona com association names enquanto references precisa do the actual table name .