Improve Activerecord With Squeel
April 24, 2013
Writing complex queries in plain ActiveRecord is sometimes cumbersome. We need to fallback to write SQL-ish queries as plain strings which could cause errors and is not a way we should query using ORM frameworks. However there is very interesting solution for this problem called Squeel. As its GitHub page says Squeel improves ActiveRecord by making the ARel awesomeness that lies beneath Active Record more accessible.
So according to its documentation we can rewrite this:
Article.where ['created_at >= ?', 2.weeks.ago]
into this:
Article.where{created_at >= 2.weeks.ago}
Pretty nice in my opinion.
Now lets look at some more complex example. We have presentations
that belongs to conference either via direct relation (conference_id
in
Presentation
model), or through some event (event_id
in Presentation
and conference_id
in Event
model). Presentation could also
be not yet assigned to any conference. Now we have admin panel with
admin users dedicated to manage certain set of conferences and we
want to scope presentations on view to only those which belongs to
managed conferences, or which aren’t yet assigned to any (BTW if you are using
ActiveAdmin you can scope the queries
using scope_to
).
We need proper scope for this task, and one could be easily written
using Squeel:
# models/presentation.rb
scope :unassigned_or_assigned_to, ->(conferences) do
includes(:sessions).where{ (conference_id >> conferences) |
(events.conference_id >> conferences) |
((conference_id == nil) & (events.conference_id == nil)) }
end
Usage of such scope is straightforward:
# models/admin_user.rb
def managed_presentations
if superadmin?
Presentation
else
Presentation.unassigned_or_assigned_to conferences
end
end
I’ll definitely consider using Squeel whenever I’ll need to write complex query.