This blog is part of our Rails 6.1 series.
Rails 6.1 adds an invert_where method that will invert all scope conditions.
Let's see an example.
class User
scope :active, -> { where(accepted: true, locked: false) }
end
>> User.all
=> #<ActiveRecord::Relation [
#<User id: 1, name: 'Rob', accepted: true, locked: true>
#<User id: 2, name: 'Jack', accepted: false, locked: false>
#<User id: 3, name: 'Nina', accepted: true, locked: false>
#<User id: 4, name: 'Oliver', accepted: false, locked: true>
Now let's query for active and inactive users
>> User.active
# SELECT * FROM Users WHERE `accepted` = 1 AND `locked` = 0
=> #<ActiveRecord::Relation [
#<User id: 3, name: 'Nina', accepted: true, locked: false>]>
>> User.active.invert_where
# SELECT * FROM Users WHERE NOT (`accepted` = 1 AND `locked` = 0)
=> #<ActiveRecord::Relation [
#<User id: 1, name: 'Rob', accepted: true, locked: true>
#<User id: 2, name: 'Jack', accepted: false, locked: false>
#<User id: 4, name: 'Oliver', accepted: false, locked: true>]>
As we can see above, if we use invert_where with multiple attributes, it
applies logical NOR, which is NOT a OR NOT b, to the WHERE clause of the
query. Using DeMorgan's Law, it can also be written as NOT (a AND b) to
match the second output.
Check out the pull request for more details.

Written byChimed Palden
Related blogs
- 01Rails 6.1 adds in: option to validate numeric rangesApril 14, 2021 · Akanksha Jain
- 02Rails 6.1 adds delegated_type to ActiveRecordApril 6, 2021 · Akhil Gautam
- 03Rails 6.1 adds nulls_first and nulls_last to ArelMarch 9, 2021 · Berin Larson
- 04Rails 6.1 adds support for PostgreSQL interval data typeJanuary 26, 2021 · Akhil Gautam