Best way to conditionally chain scopes
Since relations are chainable, it's often helpful to "build up" your search query. The exact pattern for doing that varies widely, and I'd caution against over-engineering anything, but using plain-old Ruby objects (POROs) to build up a query is common in most of the large Rails codebases I've worked in. In your case, you could probably get away with just simplifying your logic like so:
relation = Order.join(:store)
if params[:store_id]
relation = relation.store(params[:store_id])
end
if params[:status]
relation = relation.status(params[:status])
end
@orders = relation.all
Rails even provides ways to "undo" logic that has been chained previously, in case your needs get particularly complex.
You could do it like this:
query = Order
query = query.store(params[:store_id]) if params[:store_id].present?
query = query.status(params[:status]) if params[:status].present?
query = Order.joins(:store) if query == Order
Alternatively, you could also just restructure the status
and store
scopes to include the condition inside:
scope :by_status, -> status { where(status: status) if status.present? }
Then you can do this instead:
query = Order.store(params[:store_id]).by_status(params[:status])
query = Order.joins(:store) unless (params.keys & [:status, :store_id]).present?