user7067399 user7067399 - 2 days ago 6
Ruby Question

Search in one query when params are nil?

I wish to have only one query, but my problem is that when some params are nil, it will return no results, while I want it to return all. See code:

deliverer_ids = params[:deliverer_ids]&.map(&:to_i) || []
shopper_ids = params[:shopper_ids]&.map(:to_i) || []
@orders = @orders.includes(:deliverer, :shopper).where(deliverer_id: deliverer_ids, shopper_id: shopper_ids)


will return nothing and what I want to achieve is to get
Order.all
if params
deliverer_ids
and
shopper_ids
are nil.

Answer

The problem is, as I am sure you understand, that if e.g. deliverer_ids is missing, you are requiring that deliverer_id is one of... no IDs. No rows will match that, even if you specify valid IDs in shopper_ids.

Untested but I'm thinking this should work, if you change deliverer_ids to deliverer_id:

conditions = params
    .slice(:deliverer_id, :shopper_id)
    .map { |x| x.map(&:to_i) }
@orders = @orders.includes(:deliverer, :shopper).where(conditions)

If you don't rename them, then you have a bit more of a hassle.

The idea is not to pass the conditions you don't have. ActiveSupport's slice allows you to just keep parameters you want, then deliver them directly to where as conditions.

EDIT: Easier, and no need for renaming: just use compact:

deliverer_ids = params[:deliverer_ids]&.map(&:to_i)
shopper_ids = params[:shopper_ids]&.map(:to_i)
conditions = {
  deliverer_id: deliverer_ids,
  shopper_id: shopper_ids
}.compact
@orders = @orders.includes(:deliverer, :shopper).where(conditions)

Note the removal of the damaging || [] bit. In fact, I didn't test, but it may even work with your original code, as long as you drop that bit - ActiveRecord might be smart enough to not include any restrictions if the restriction is nil.

Comments