Let's say we have the following:
irb> Post.where(:hidden => true).to_sql
=> "SELECT `posts`.* FROM `posts` WHERE posts.hidden = 1"
Could we somehow get an inverted SQL query out of it?
What I am looking for, should probably look like this:
irb> Post.where(:hidden => true).invert.to_sql
=> "SELECT `posts`.* FROM `posts` WHERE NOT (posts.hidden = 1)"
Whereas an instance of ActiveRecord::Relation is a representation of a query that can be run against your database (but wasn't run yet). Once you run that query by calling to_a , each , first etc. on that Relation a single instance or an array of ActiveRecord::Base instances will be returned.
From the documentation, it seems like the :inverse_of option is a method for avoiding SQL queries, not generating them. It's a hint to ActiveRecord to use already loaded data instead of fetching it again through a relationship.
ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending. Edit: as Mike points out, in this case ActiveRecord is a module... ActiveRecord is defined as a module in Rails, github.com/rails/rails/tree/master/activerecord/lib/…
Rails 7 now allows automatic inverse_of detection for associations with scopes. Feb 1, 2022 , by Swaathi Kakarla. 2 minute read. ActiveRecord has many tricks up its sleeve. One of the many is this seemingly simple association option called inverse_of , which helps us to explicitly declare bi-directional associations.
Starting from Rails 7, there is a new invert_where method.
According to the docs, it:
Allows you to invert an entire where clause instead of manually applying conditions.
class User
scope :active, -> { where(accepted: true, locked: false) }
end
User.where(accepted: true)
# WHERE `accepted` = 1
User.where(accepted: true).invert_where
# WHERE `accepted` != 1
User.active
# WHERE `accepted` = 1 AND `locked` = 0
User.active.invert_where
# WHERE NOT (`accepted` = 1 AND `locked` = 0)
Be careful because this inverts all conditions before invert_where call.
class User
scope :active, -> { where(accepted: true, locked: false) }
scope :inactive, -> { active.invert_where } # Do not attempt it
end
# It also inverts `where(role: 'admin')` unexpectedly.
User.where(role: 'admin').inactive
# WHERE NOT (`role` = 'admin' AND `accepted` = 1 AND `locked` = 0)
Sources:
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