Hi RoR folks! Hope you are all doing well and celebrating Ruby's birthday!
Today in this post we are gonna talk about Arel and here is a list of what we are gonna discuss:
What is Arel?
History of Arel
Advantages of using Arel
Arel basic syntax
Conclusion
What is Arel?
Arel is a library that is being used to help us to write SQL queries in a much easier, more readable, and cleaner way. Also, it helps us to write both simple and complex queries.
History of Arel
Arel was introduced in Rails 3 but it is now bundled into the Active Record gem and maintained in the rails/rails repository.
Advantages of using Arel
Readability
Since all SQL queries are strings, it may be hard to read, edit, or break down a complex query.
Reusability
It’s much easier to reuse Arel queries as they are made up of interlinking nodes – a safer alternative than string interpolation.
Reliability
If we join another table, our query will immediately break due to the ambiguity of the id column. Even if we qualify the columns with the table name, this will break as well if Rails decides to alias the table name.
Arel basic syntax
- Arel Table
To start creating queries, we need to decide which Model we are going to query on. Then, we need to interact with the Arel Table for that Model and this could be done by using the arel_table
method
users = User.arel_table
Here there is an Arel::Table
object created for that table we are going to work on. After that object is created for that data table, Arel converts each column of that Table into an Arel::Node
that we can execute different methods that are supported by this library on it. The most common methods in Arel are:
Equal (eq)
Not Equal (not_eq)
Greater Than (gt)
Less Than (lt)
Greater Than Or Equal (gteq)
Less Than Or Equal (lteq)
Or (or)
And (and)
NOTE: To see all Arel predications you can run:
Arel::Predications.instance_methods
- Where queries
We can say that more than 75% of all the queries are built using where
method cause it's used to filter our data and select a specific part based on a specific true condition. Since where
method can take different kinds of arguments, we can pass custom-built Arel queries to it and this could be so powerful.
NOTE: To break a query to use Arel, there's a good rule to break out a method anywhere the word
AND
orOR
is used.
class UserMembershipQuery
def members
users = User.where(public_profile.and(group_member))
end
private
def table
User.arel_table
end
def public_profile
table[:private].eq(false)
end
def group_member
table[:group_member].eq(true)
end
end
users[:id].in([1,2,3]).to_sql
=> "`users`.`id` IN (1, 2, 3)"
users[:id].gt(2).to_sql
=> "`users`.`id` > 2"
users[:id].eq(3).to_sql
=> "`users`.`id` = 3"
User.where(table[:id].in([1,2,3])).to_sql
# SELECT "users".* FROM "users" WHERE "users"."id" IN (1, 2, 3)
- Projection queries
Projection queries are the same as the select
queries, we use the project
to specify the nodes we want to select or return. This would need to be executed directly as SQL and can not easily be combined with ActiveRecord queries.
User.where(table[:role].eq(:admin)).project(:email).to_sql
=> "SELECT email FROM `users` WHERE `users`.`role` = 2"
And to connect these queries with the Active Record is a little bit more complex:
ActiveRecord::Base.connection.exec_query User.where(users[:role].eq(:admin)).project(:email)
- Joins
Here where we can see that Arel is really useful, cause writing join queries using Arel is a lot more simple and readable than SQL.
subscriptions = Subscription.arel_table
table.join(subscriptions)
Yes! It's that simple! We can also determine the relationship
table.join(subscriptions, Arel::Nodes::OuterJoin).on(table[:id].eq(subscriptions[:user_id]))
And to write join with a condition
table.joins(:subscriptions).merge(Subscription.where(active: true))
There are other methods that we can use to scope different queries: Like sum
, average
, count
, min
, and max
that we can use to perform different operations on values
table.project(table[:rate].average)
Conclusion
In this article, we slightly discussed the basics of Arel like what's it and its history and its basic syntax but it has a lot more stuff that could be very helpful, and there's a lot more to learn about it, so, I recommend you to go through Arel documentation and get your hand dirty and start using it. If u have any comments or any feedback I will be happy to hear from your side.
Reviewed by Farha Zane ❤︎