Yuval Karmi Yuval Karmi - 3 months ago 67
Ruby Question

Is it possible to negate a scope in Rails 3?

I have the following scope for my class called

Collection
:

scope :with_missing_coins, joins(:coins).where("coins.is_missing = ?", true)


I can run
Collection.with_missing_coins.count
and get a result back -- it works great!
Currently, if I want to get collections without missing coins, I add another scope:

scope :without_missing_coins, joins(:coins).where("coins.is_missing = ?", false)


I find myself writing a lot of these "opposite" scopes. Is it possible to get the opposite of a scope without sacrificing readability or resorting to a lambda/method (that takes
true
or
false
as a parameter)?

Something like this:

Collection.!with_missing_coins


Thanks!

Answer

I wouldn't use a single scope for this, but two:

scope :with_missing_coins, joins(:coins).where("coins.is_missing = ?", true)
scope :without_missing_coins, joins(:coins).where("coins.is_missing = ?", false)

That way, when these scopes are used then it's explicit what's happening. With what numbers1311407 suggests, it is not immediately clear what the false argument to with_missing_coins is doing.

We should try to write code as clear as possible and if that means being less of a zealot about DRY once in while then so be it.