squeel
TRANSCRIPT
-
8/13/2019 Squeel
1/9
Squeel
Squeel lets you write your Active Record queries with fewer strings, and more Ruby, by
making the Arel awesomeness that lies beneath Active Record more accessible.
Squeel lets you rewrite...
Article.where ['created_at >= ?', 2.weeks.ago]
...as...
Article.where{created_at >= 2.weeks.ago}
This is agood thing. If you don't agree, Squeel might not be for you. The above is ust a
sim!le e"am!le ## Squeel's ca!able of a whole lot more. $ee! reading.
Getting started
In your %emfile&
gem "sqeel" ! ast o##iciall$ released gem! gem "sqeel", %git => "git%&&gith.com&er(ie&sqeel.git" ! )rack gitre*o
Then bundle as usual.
If you'd like to customie Squeel's functionality by enabling core e"tensions for hashes orsymbols, or aliasing some !redicates, you can create a sam!le initialier with&
+ rails g sqeel%i(itialier
The Squeel Query DSL
Squeel enhances the normal Active Record query methods by enabling them to acce!t blocks.
Inside a block, the Squeel query (S) can be used. *ote the use of curly braces in these
e"am!les instead of !arentheses. {}denotes a Squeel (S) query.
Stubs and key!aths are the two !rimary building blocks used in a Squeel (S) query, so we'llstart by taking a look at them. +ost of the other e"am!les that follow will be based on this
symbol#less block synta".
An important gotcha, before we begin:The Squeel (S) works its magic using
i(sta(ce_e-al. If you've been working with Ruby for a while, you'll know immediately that
this means that insidea Squeel (S) block, sel#isn't the same thing that it is outsidethe
block.
This carries with it an im!ortant im!lication& Instance variables and instance methods
inside the block won't refer to your object's variablesmethods!
-
8/13/2019 Squeel
2/9
-
8/13/2019 Squeel
3/9
All of the Arel !redication methods can be accessed inside the Squeel (S), via their
method name, an alias, or an an o!erator, to create Arel !redicates, which are used in 9:1
or :ABCclauses.
S"# $redication %perator Alias
8 eq 88
98 not:eq 98 1.; only2, < 1.=2
)I$> matches 87 like
*?T )I$> does:not:match 97 1.; only2 not:like
@ lt @
@8 lteq @8 lte
gt
8 gteq 8 gte
I* in
*?T I* not:in @@
)et's say we want to generate this sim!le query&
34) "*eo*le".5 6178 *eo*le 9:1 "*eo*le"."(ame" = '@oe Dlow'
All of the following will generate the above SB)&
erso(.where '@oe Dlow'erso(.where{{(ame => '@oe Dlow'}}erso(.where{{(ame.eq => '@oe Dlow'}}erso(.where{(ame.eq '@oe Dlow'}
erso(.where{(ame == '@oe Dlow'}
*ot a very e"citing e"am!le since equality is handled ust fine via the first e"am!le in
standard Active Record. Cut consider the following query&
34) "*eo*le".5 6178 *eo*le9:1
-
8/13/2019 Squeel
4/9
. To read code with SB) inter!olation, the structure of the SB) query must first be
considered, then we must cross#reference the values to be substituted with their
!laceholders. This carries with it a small but !erce!tible 1and annoying92 conte"t shift
during which we sto! thinking about the com!arison being !erformed, and instead
!lay count the arguments, or, in the case of namedDhash inter!olations, find the
word. The Squeel synta" !laces both sides of each com!arison in !ro"imity to oneanother, allowing us to focus on what our code is doing.
/. In the first e"am!le, we're starting off with Ruby, switching conte"t to SB), and then
back to Ruby, and while we s!end time in SB)#land, we're stuck with SB) synta",
whether or not it's the best way to e"!ress what we're trying to do. 4ith Squeel, we're
writing Ruby from start to finish. And with Ruby synta" comes fle"ibility to e"!ress
the query in the way we see fit.
Predicate aliases
That last bit is im!ortant. 4e can mi" and match !redicate methods with o!erators and take
advantage of Ruby's o!erator !recedence or !arenthetical grou!ing to make our intentions
more clear, on the first read#through. And if we don't like the way that the e"isting
!redications read, we can create our own aliases in a Squeel configure block&
3qeel.co(#igre do /co(#ig/ co(#ig.alias_*redicate %is_less_tha(, %lte(derso(.where{salar$.is_less_tha( IJJJJ}.to_sql! => 34) "*eo*le".5 6178 "*eo*le" 9:1 "*eo*le"."salar$" H IJJJJ
And while we're on the to!ic of hel!ing you make your code more e"!ressive...
Compound conditions
)et's say you want to check if a Eerson has a name like one of several !ossibilities.
(ames = ['r(ieF', '@oeF', '8ar$F']erso(.where 34) "*eo*le".5 6178 "*eo*le"! 9:1
-
8/13/2019 Squeel
5/9
Sifters
Sifters are like little sni!!ets of conditions that take !arameters. )et's say that you have a
model called Article, and you often want to query for articles that contain a string in the title
or body. So you write a sco!e&
de# sel#.title_or_od$_co(tai(s
-
8/13/2019 Squeel
6/9
! 9:1 "articles"."athor_id" 34) "*eo*le".5 6178 "*eo*le"! 6) 7M)1 @7 "articles" 7 "articles"."*erso(_id" = "*eo*le"."id"ote.;oi(s{(otale 34) "(otes".5 6178 "(otes"! 6) 7M)1 @7 "*eo*le"! 7 "*eo*le"."id" = "(otes"."(otale_id"! AG "(otes"."(otale_t$*e" = 'erso('
These can also be used inside key!aths&
ote.;oi(s{(otale 34) "(otes".5 6178 "(otes"! 1 @7 "*eo*le" 7 "*eo*le"."id" = "(otes"."(otale_id"! AG "(otes"."(otale_t$*e" = 'erso('! 1 @7 "articles" 7 "articles"."*erso(_id" = "*eo*le"."id"
0ou can refer to these associations when constructing other !arts of your query, and they'll be
automatically ma!!ed to the !ro!er table or table alias This is most noticeable when using
self#referential associations&
erso(.;oi(s{childre(.*are(t.childre(}. where{
-
8/13/2019 Squeel
7/9
...and you can easily give it an alias&
*erso( = erso(.select{ coalesce'.as "Aric 3mithQdiddl$"*.(ame_with_de#alt! => "Aric 3mith"
Compatibility with Active Record
+ost of the new functionality !rovided by Squeel is accessed with the new block#style
where{}synta".
-
8/13/2019 Squeel
8/9
All your e"isting code that uses !lain Active Record where
-
8/13/2019 Squeel
9/9
erso(.;oi(s %comme(ts. where {%comme(ts => {%od$.matches => ':elloR'}}! => 34) "*eo*le".5 6178 "*eo*le"! 1 @7 "articles" 7 "articles"."*erso(_id" = "*eo*le"."id"! 1 @7 "comme(ts" 7 "comme(ts"."article_id" = "articles"."id"! 9:1 "comme(ts"."od$" E ':elloR'
This should hel! to smooth over the transition to the new (S).
Contributions
If you'd like to su!!ort the continued develo!ment of Squeel, !lease consider making a
donation.
To su!!ort the !roect in other ways&
-se Squeel in your a!!s, and let me know if you encounter anything that's broken or
missing. A failing s!ec is awesome. A !ull request is even better9
S!read the word on Twitter, 6acebook, and elsewhere if Squeel's been useful to you.
The more !eo!le who are using the !roect, the quicker we can find and fi" bugs9
Copyright
Jo!yright K /L >rnie +iller
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N7QP5N3UB76MEhttps://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N7QP5N3UB76MEhttp://twitter.com/erniemillerhttps://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N7QP5N3UB76MEhttps://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N7QP5N3UB76MEhttp://twitter.com/erniemiller