September 15, 2021
This blog is part of our Rails 7 series.
ActiveRecord is
one of the most powerful features in Rails. With ActiveRecord we can easily
query and handle database objects without writing any SQL.
By using ActiveRecord Query Interface, we can perform various query operations
like Joins, Group, Find, Order. We can also chain relations with
where, and, or, not but for and or or the two chaining relations
must be structurally compatible.
For any two relations to be
Structurally Compatible
they must be scoping the same model, and they must differ only by the where
clause when no group clause has been defined. If a group clause is present
then the relations must differ by the having clause. Also, Neither relation
may use a limit, offset, or distinct method.
Previously for and or or query methods, we needed to make sure that the two
relations are structurally compatible otherwise ActiveRecord would raise an
error.
However,
Rails 7 has added ActiveRecord::Relation#structurally_compatible?
which provides a method to easily tell if two relations are structurally
compatible. We can use this method before we run and or or query methods on
any two relations.
Let's assume we have two models Blog and Post with the following relations
# app/models/blog.rb
class Blog < ApplicationRecord
has_many :posts
end
# app/models/post.rb
class Post < ApplicationRecord
belongs_to :blog
end
If we run or query between incompatible relations we would get an
ArgumentError.
relation_1 = Blog.where(name: 'bigbinary blog')
relation_2 = Blog.joins(:posts).where(posts: { user_id: current_user.id})
begin
relation_1.or(relation_2)
rescue ArgumentError
# Rescue ArgumentError
end
We can check the structural compatibility of the two relations.
relation_1 = Blog.where(name: 'bigbinary blog')
relation_2 = Blog.where(user_id: current_user.id)
if relation_1.structurally_compatible?(relation_2) # returns true
relation_1.or(relation_2)
end
Check out this pull request for more details.
If this blog was helpful, check out our full blog archive.