When you're using a boolean in Rails with Active Record, and you ask (say) visible?
, it checks the column for whether it is true
or not. If it is false
or nil
, visible?
will return false
.
How do you scope a boolean to ask if the ?
method would return false? I have this:
scope :visible, where(hide: [nil, false])
but am wondering if there is a cleaner way. Is there a way to write this scope without explicitly saying both nil
and false
? If we were after the opposite, we could just write
scope :invisible, where(hide: true)
which seems cleaner. What's the best code for the visible scope?
Use a default value on the column. This is good for two reasons: you have only two possible values in your DB, making your code easier. And booleans are either true or false, not nil, not maybe, not foobar. True and false. "I'd rather avoid having to get the DB strictly false/true though" is a moot argument for a boolean column.
If you need more than 2 states, use a state machine or something similar - then its not a boolean column/state anymore.
As of Rails 4, you can accomplish this like so:
# This will give you any hidden records
scope :invisible, -> { where(hide: true) }
# And this will give you any records that aren't hidden – whether nil *or* false
scope :visible, -> { where.not(hide: true) }
Although Tanel's answer doesn't actually answer the question at hand, which is "What's the best code for the visible scope?", I would definitely echo what he said that a boolean column should always be either true
or false
.
Really, no database should even allow a column declared as boolean
to be anything other than true
or false
because, otherwise, it's not truly boolean. But that's a separate can of worms. :-D
I'd go with:
scope :visible, -> { where(hide: false) }
scope :invisible, -> { where(hide: true) }
In SQL NULL
represents a missing or unknown value so strictly speaking records with hide = NULL
are neither visible nor invisible.
Almost the same as Stefan's answer, a bit simplified:
scope :visible, where(hide: false)
scope :invisible, where(:hide)
It works for PostgreSQL, but I'm not sure will it work for other databases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With