2. What is Arel?
Arel is a SQL AST manager for Ruby
Active Record uses Arel to build queries
It adapts to various RDBMSes
It is intended to be a framework framework
9. It only supports equality
Dog.where('age > ?', 5)
# WHERE age > 5
10. No support for OR (until 5.0.0)
Dog.where('age = ? OR name = ?', 5, 'Fido')
# WHERE age = 5 OR name = 'Fido'
11. No support for explicit joins
Dog.joins(
'INNER JOIN owners o ON o.id = dogs.owner_id'
)
12. No outer joins (without loading everything into memory)
Dog.joins(
'LEFT OUTER JOIN owners ON owners.id = dogs.owner_id'
)
13. Composability goes out the window
class Dog < ActiveRecord::Base
scope :old, -> { where('age > ?', 5) }
scope :named_fido, -> { where(name: 'Fido') }
def self.named_fido_or_old
where('age > ? OR name = ?', 5, 'Fido')
end
end
14. Not to mention...
Not database agnostic
No syntax checking
Question marks can be tough to track down
What ever happened to the 80 characters/line?
Model
.joins('LEFT JOIN candidacies as search_candidates on search_candidates.contact_id = contacts.id'
.joins('LEFT JOIN searches as contact_searches on search_candidates.search_id = contact_searches.id'
.where('(lower(contact_searches.name) like ? AND search_candidates.deleted=?)', "%#{name}%".downcase
17. Predications
age = Dog.arel_table[:age]
name = Dog.arel_table[:name]
Dog.where age.gt(5)
# WHERE "dogs"."age" > 5
Dog.where age.not_eq(5)
# WHERE "dogs"."age" != 5
Dog.where name.matches('%ido')
# WHERE "dogs"."name" LIKE '%ido'
18. Grouping
id = Dog.arel_table[:id]
age = Dog.arel_table[:age]
name = Dog.arel_table[:name]
Dog.where id.gt(5).and(
name.eq('Ronald').or(
age.eq(3)
)
)
# WHERE (
# "dogs"."id" > 5 AND (
# "dogs"."name" = 'Ronald' OR
# "dogs"."age" = 3
# )
# )
21. Composability
class Dog < ActiveRecord::Base
scope :old, -> { where(old_arel) }
scope :named_fido, -> { where(named_fido_arel) }
def self.old_or_named_fido
where named_fido_arel.or(old_arel)
end
def self.old_arel
arel_table[:age].gt(5)
end
def self.named_fido_arel
arel_table[:name].eq('Fido')
end
end
28. Extremely similar to Squeel
Under 500 LOC
No core exts
No monkey patches!
As conservative as possible
29. Predications
Dog.where.has { age > 5 }
# WHERE ("dogs"."age" > 5)
Dog.where.has { name != 'Jeff' }
# WHERE ("dogs"."name" != 'Jeff')
Dog.where.has { name =~ '%ido' }
# WHERE ("name" LIKE '%ido')
30. Grouping
Dog.where.has {
(id > 5).and(
(name == 'Ronald').or(age == 3)
)
}
# WHERE (
# "dogs"."id" > 5 AND (
# "dogs"."name" = 'Ronald' OR
# "dogs"."age" = 3
# )
# )
31. Dog.selecting { age.maximum }
# SELECT MAX("dogs"."age") FROM "dogs"
Dog.selecting { (id + 100) / 20 }
# SELECT ("dogs"."id" + 100) / 20 FROM "dogs"
Dog.selecting { coalesce(name, quoted('Ronald')) }
# SELECT coalesce("dogs"."name", 'Ronald') FROM "dogs"
Dog.selecting { name.op('||', quoted('diddly')) }
# SELECT "dogs"."name" || 'diddly' FROM "dogs"