Reputation: 407
I am having Orders with status(Pending, and Completed), Pickup_date, dropoff_date. And i want to order conditionally on the basis of status.
Upvotes: 1
Views: 62
Reputation: 1004
I would highly recommend not to mix scope responsibilities. If you do it all in one scope called order_by_time
, the naming is confusing, if I see Order.order_by_time
I will assume that it only orders the result, and I will be truly surprised when I learn the reality after checking the implementation...
I would recommend some isolation, which provides more flexibility for later use:
scope :pending, -> { where(status: :pending) }
scope :completed, -> { where(status: :completed) }
scope :order_by_pickup_time, -> { order(pickup_time: :desc) }
scope :order_by_dropof_time, -> { order(dropof_time: :desc) }
Then you could use them:
Order.pending.order_by_pickup_time
Order.completed.order_by_dropof_time
Upvotes: 1
Reputation: 407
We can do it in single query in scope as :
scope :order_by_time, -> { order("CASE WHEN (orders.state IN ('pending', 'picked_up')) THEN 'orders.pick_up_time' WHEN (orders.state IN ('ready_for_delivery', 'delivered')) THEN 'orders.delivery_time' END") }
Upvotes: 1
Reputation: 5942
I suggest to use conditionals query
class Orders < ApplicationRecord
scope :order_by_pickup_time, ->(status) { where("created_at < ?", pickup_time) if status == "pending" }
end
Like the other examples, this will behave similarly to a class method.
class Orders < ApplicationRecord
def self.order_by_pickup_time(status)
where("created_at < ?", pickup_time) if status == "pending"
end
end
However, there is one important caveat: A scope will always return an ActiveRecord::Relation object, even if the conditional evaluates to false, whereas a class method, will return nil. This can cause NoMethodError when chaining class methods with conditionals, if any of the conditionals return false.
Upvotes: 0
Reputation: 12320
In the model
scope :pending, -> { where(status: "pending").order(pickup_time: :desc) }
scope :completed, -> { where(status: "completed").order(dropof_time: :desc) }
Then use Order.pending
it will order by pick up time it with all pending orders
Then use Order.completed
it will order it with all conmpleted orders by dropoff time
Upvotes: 0