Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

301
Visualizações
Rails 4: Using PostgreSQL function in order causes error in query due to the includes table not being joined

I found an odd problem with Rails 4 Active Record queries where the includes table is not joined if I use a PostgreSQL function in the order. This same query works fine if I remove the PostgreSQL function.

This works fine...

Widget.includes(:sprocket).order("sprockets.name").all

This fails because the includes relationship is not joined...

Widget.includes(:sprocket).order("lower(sprockets.name)").all

Notice the only thing different is the lower(sprockets.name).

I know I can add .references like this...

Widget.includes(:sprocket).references(:sprockets).order("lower(sprockets.name)").all

That will work, but then what is the purpose of the includes?

I've found that replacing includes with eager_load works also, but again, what is the purpose of includes then?

Widget.eager_load(:sprocket).order("lower(sprockets.name)").all

In Rails 3, just using includes works fine. I guess I have a lot of code to change, but just hoping there is an easier fix?

Thank you

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Suppose you need to get the user name of first five post. You quickly write the query below and go enjoy your weekend.

posts = Post.limit(5)

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

Good. But let's look at the queries

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 to fetch all posts and 1 query to fetch users for each post results in a total of 6 queries. Check out the solution below which does the same thing, just 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)

There’s one little difference. Add includes(:posts) to your query, and problem solved. Quick, nice, and easy.

But don’t just add includes in your query without understanding it properly. Using includes with joins might result in cross-joins depending on the situation, and you don’t need that in most cases.

If you want to add conditions to your included models you’ll have to explicitly reference them. For example:

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

Will throw an error, but this will work:

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

Note that includes works with association names while references needs the actual table name.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda