[ruby-on-rails] How to return an empty ActiveRecord relation?



3 Answers

A more portable solution that doesn't require an "id" column and doesn't assume there won't be a row with an id of 0:

scope :none, where("1 = 0")

I'm still looking for a more "correct" way.

Question

If I have a scope with a lambda and it takes an argument, depending on the value of the argument, I might know that there will not be any matches, but I still want to return a relation, not an empty array:

scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }

What I really want is a "none" method, the opposite of "all", that returns a relation that can still be chained, but results in the query being short-circuited.




There are also variants, but all of these are making request to db

where('false')
where('null')



Coming in Rails 4

In Rails 4, a chainable ActiveRecord::NullRelation will be returned from calls like Post.none.

Neither it, nor chained methods, will generate queries to the database.

According to the comments:

The returned ActiveRecord::NullRelation inherits from Relation and implements the Null Object pattern. It is an object with defined null behavior and always returns an empty array of records without quering the database.

See the source code.




I think I prefer the way this looks to the other options:

scope :none, limit(0)

Leading to something like this:

scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }



Related