Rails scope that does nothing for NOT IN values


I have a Rails 3 scope that excludes an array of ids.

What is the best way to write the scope so that it does nothing when the array is empty and is still chainable? I currently have this, which works, but seems a little hokey:

scope :excluding_ids, 
         lambda {|ids| ids.empty? ? relation : where('id not in (?)', ids) }

If I do not have the "ids.empty? ? relation :" bit, when ids is empty the SQL generated is

... ID not in (NULL) ...

which will always return nothing. So something like:

Model.excluding_ids([]).where('id > 0')

returns no results.

Best Solution

If the ids array is empty then don't return anything.

scope :excluding_ids, lambda { |ids|
  where(['id NOT IN (?)', ids]) if ids.any?

The query will run without any additional constraints on the query if there are no ids.

Related Question