pzin
pzin

Reputation: 4248

Sort ActiveRecord collection by different attributes depending on a third attribute

I have an Order model with those attributes:

What I am trying to do, is to sort two collections by created_at or delivery_at depending on its status.

On the model, I created a method which checks the status order and return created_at or delivery_at datetime.

def status_date
  if status == 'on_delivery'
    delivered_at.to_datetime
  else
    created_at.to_datetime
  end
end

And then in the controller:

created = Order.where(status: 'open')
on_delivery = Order.where(stauts: 'on_delivery')

orders = created + on_delivery
orders.sort_by(&:status_date)

Which is not working.

I am trying to achieve a chronological list of orders, but DateTime should be related to its status.

Upvotes: 0

Views: 53

Answers (1)

mu is too short
mu is too short

Reputation: 434665

You can do it all in the database by querying both statuses at once and then using an SQL CASE expression for the ordering:

case status
when 'open' then created_at -- if the status is open then use created_at
else delivered_at           -- otherwise use delivered_at
end

You only have two statuses so those branches are sufficient.

Putting it together:

orders = Order.where(status: %w[open on_delivery])
              .order(Arel.sql("case status when 'open' then created_at else delivered_at end"))

The Arel.sql is needed to get an SQL string past #order without complaint in Rails5 (and will be mandatory in Rails6).

Upvotes: 1

Related Questions