vendredi 17 juin 2016

Ordering records from `has_many through, -> { distinct }` by an associated value

I'm using a SELECT DISTINCT and having issues trying to order my results by an associated value. Take this example (in Rails):

I have a Cook model with a distinct customers association:

has_many :customers, -> { distinct }, through: :orders, source: :user

It's distinct because I only want to count customers once, even if they have multiple orders.

The generated SQL for this is:

> cook.customers.to_sql
=> "SELECT DISTINCT "users".* FROM "users"
 INNER JOIN "orders" ON "users"."id" = "orders"."user_id"
 INNER JOIN "meals" ON "orders"."meal_id" = "meals"."id"
 WHERE "meals"."cook_id" = 1"

This works fine! (the orders table is associated through meals but feel free to ignore)

I want to order this list of customers by the most recent created_at value of the orders of those customers. But when I do this, I get an error:

cook.customers.order('orders.created_at DESC').to_sql
=> "SELECT DISTINCT "users".* FROM "users"
    INNER JOIN "orders" ON "users"."id" = "orders"."user_id"
    INNER JOIN "meals" ON "orders"."meal_id" = "meals"."id        "WHERE "meals"."cook_id" = 1  ORDER BY orders.created_at DESC"
  > cook.customers.order('orders.created_at DESC')
  ActiveRecord::StatementInvalid: PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
  LINE 1: ...eals"."id" WHERE "meals"."cook_id" = $1  ORDER BY orders.cre...

Even if I explicitly join the tables (don't think I should need to because of has_many through), this still doesn't work.

cook.customers.joins(:orders).order('orders.created_at DESC').to_sql
=> "SELECT DISTINCT "users".* FROM "users" INNER JOIN "orders" "orders_users" ON "orders_users"."user_id" = "users"."id" INNER JOIN "orders" ON "users"."id" = "orders"."user_id" INNER JOIN "meals" ON "orders"."meal_id" = "meals"."id" WHERE "meals"."cook_id" = 1  ORDER BY orders.created_at DESC"

Any clues? I'm looking for a solution that will return an ActiveRecord relation (so no using sort_by), because I plan on chaining additional queries to this.

Thank you :)

Aucun commentaire:

Enregistrer un commentaire