Rails scope that does nothing for NOT IN values

2019-03-25 02:57发布

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.

4条回答
男人必须洒脱
2楼-- · 2019-03-25 03:37

Here's a slight variation on Douglas' answer, using ruby 1.9 stabby lambda syntax and without the brackets in the where method.

scope :excluding_ids, ->(ids) {where("id NOT IN (?)", ids) if ids.any?}
查看更多
混吃等死
3楼-- · 2019-03-25 03:42

How about the following? (It still checks for an empty array though, so if that's what you're trying to avoid it's not much of an improvement :)

scope :excluding_ids,
     lambda {|ids| (ids.empty? && relation) || where('id not in (?)', ids) }
查看更多
Anthone
4楼-- · 2019-03-25 03:50

In Rails 4 you can use:

scope :excluding_ids, ->(ids) { where.not(id: ids) }
查看更多
smile是对你的礼貌
5楼-- · 2019-03-25 03:59

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.

查看更多
登录 后发表回答