squeel 1.0.18 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.ruby-gemset +1 -0
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +2 -7
  4. data/CHANGELOG.md +9 -0
  5. data/Gemfile +2 -2
  6. data/README.md +223 -147
  7. data/lib/generators/templates/squeel.rb +1 -1
  8. data/lib/squeel/adapters/active_record.rb +1 -1
  9. data/lib/squeel/adapters/active_record/4.0/compat.rb +17 -0
  10. data/lib/squeel/adapters/active_record/4.0/context.rb +1 -0
  11. data/lib/squeel/adapters/active_record/4.0/preloader_extensions.rb +1 -0
  12. data/lib/squeel/adapters/active_record/4.0/relation_extensions.rb +126 -0
  13. data/lib/squeel/adapters/active_record/base_extensions.rb +1 -1
  14. data/lib/squeel/adapters/active_record/context.rb +10 -10
  15. data/lib/squeel/adapters/active_record/relation_extensions.rb +24 -16
  16. data/lib/squeel/configuration.rb +1 -0
  17. data/lib/squeel/constants.rb +2 -2
  18. data/lib/squeel/context.rb +2 -2
  19. data/lib/squeel/dsl.rb +1 -1
  20. data/lib/squeel/nodes.rb +2 -0
  21. data/lib/squeel/nodes/binary.rb +1 -1
  22. data/lib/squeel/nodes/function.rb +5 -5
  23. data/lib/squeel/nodes/join.rb +2 -2
  24. data/lib/squeel/nodes/key_path.rb +10 -5
  25. data/lib/squeel/nodes/literal.rb +1 -1
  26. data/lib/squeel/nodes/nary.rb +5 -7
  27. data/lib/squeel/nodes/node.rb +6 -0
  28. data/lib/squeel/nodes/operation.rb +1 -1
  29. data/lib/squeel/nodes/order.rb +1 -1
  30. data/lib/squeel/nodes/predicate.rb +5 -5
  31. data/lib/squeel/nodes/predicate_methods.rb +11 -2
  32. data/lib/squeel/nodes/sifter.rb +2 -2
  33. data/lib/squeel/nodes/stub.rb +2 -2
  34. data/lib/squeel/nodes/unary.rb +1 -1
  35. data/lib/squeel/version.rb +1 -1
  36. data/lib/squeel/visitors/predicate_visitation.rb +6 -6
  37. data/lib/squeel/visitors/predicate_visitor.rb +1 -1
  38. data/lib/squeel/visitors/visitor.rb +20 -20
  39. data/spec/spec_helper.rb +6 -4
  40. data/spec/squeel/adapters/active_record/base_extensions_spec.rb +6 -6
  41. data/spec/squeel/adapters/active_record/relation_extensions_spec.rb +55 -24
  42. data/spec/squeel/core_ext/symbol_spec.rb +2 -2
  43. data/spec/squeel/nodes/key_path_spec.rb +3 -3
  44. data/spec/squeel/nodes/predicate_operators_spec.rb +4 -4
  45. data/spec/squeel/visitors/predicate_visitor_spec.rb +11 -11
  46. data/spec/squeel/visitors/visitor_spec.rb +9 -9
  47. data/spec/support/models.rb +25 -7
  48. data/spec/support/schema.rb +1 -1
  49. data/squeel.gemspec +4 -4
  50. metadata +19 -12
@@ -0,0 +1 @@
1
+ squeel
@@ -0,0 +1 @@
1
+ ruby-1.9.3
@@ -1,13 +1,8 @@
1
1
  rvm:
2
- - 1.8.7
3
2
  - 1.9.3
4
- # TODO: Re-enable when updates to Rubinius on
5
- # Travis stop randomly breaking specs that
6
- # pass on MRI. :(
7
- # - rbx-18mode
8
- # - rbx-19mode
9
3
 
10
4
  env:
11
- - RAILS=3-2-stable
5
+ - RAILS=4-0-stable AREL=master
6
+ - RAILS=3-2-stable AREL=3-0-stable
12
7
  - RAILS=3-1-stable AREL=2-2-stable
13
8
  - RAILS=3-0-stable AREL=2-0-stable
@@ -1,3 +1,12 @@
1
+ ## 1.1.0 (2013-07-14)
2
+
3
+ * Support for Active Record 4.0.0!
4
+ * Deprecated core extensions. In Squeel 2.0, the DSL will be the way to
5
+ construct queries, and Symbol/Hash extensions will go away.
6
+ * Prefix generated sifter methods with `sifter_` so as not to interfere with
7
+ similarly-named scopes.
8
+ * No longer mutate And nodes when using `&` and `-` on the node
9
+
1
10
  ## 1.0.18 (2013-03-07)
2
11
 
3
12
  * Stop treating nils as quotable. Fixes issue #221.
data/Gemfile CHANGED
@@ -3,8 +3,8 @@ gemspec
3
3
 
4
4
  gem 'rake'
5
5
 
6
- rails = ENV['RAILS'] || '3-2-stable'
7
- arel = ENV['AREL'] || '3-0-stable'
6
+ rails = ENV['RAILS'] || '4-0-stable'
7
+ arel = ENV['AREL'] || 'master'
8
8
 
9
9
  arel_opts = case arel
10
10
  when /\// # A path
data/README.md CHANGED
@@ -1,15 +1,19 @@
1
1
  # Squeel [![Build Status](https://secure.travis-ci.org/ernie/squeel.png)](http://travis-ci.org/ernie/squeel) [![endorse](http://api.coderwall.com/ernie/endorsecount.png)](http://coderwall.com/ernie)
2
2
 
3
3
  Squeel lets you write your Active Record queries with fewer strings, and more Ruby,
4
- by making the ARel awesomeness that lies beneath Active Record more accessible.
4
+ by making the Arel awesomeness that lies beneath Active Record more accessible.
5
5
 
6
6
  Squeel lets you rewrite...
7
7
 
8
- Article.where ['created_at >= ?', 2.weeks.ago]
8
+ ```ruby
9
+ Article.where ['created_at >= ?', 2.weeks.ago]
10
+ ```
9
11
 
10
12
  ...as...
11
13
 
12
- Article.where{created_at >= 2.weeks.ago}
14
+ ```ruby
15
+ Article.where{created_at >= 2.weeks.ago}
16
+ ```
13
17
 
14
18
  This is a _good thing_. If you don't agree, Squeel might not be for you. The above is
15
19
  just a simple example -- Squeel's capable of a whole lot more. Keep reading.
@@ -18,8 +22,10 @@ just a simple example -- Squeel's capable of a whole lot more. Keep reading.
18
22
 
19
23
  In your Gemfile:
20
24
 
21
- gem "squeel" # Last officially released gem
22
- # gem "squeel", :git => "git://github.com/ernie/squeel.git" # Track git repo
25
+ ```ruby
26
+ gem "squeel" # Last officially released gem
27
+ # gem "squeel", :git => "git://github.com/ernie/squeel.git" # Track git repo
28
+ ```
23
29
 
24
30
  Then bundle as usual.
25
31
 
@@ -27,7 +33,9 @@ If you'd like to customize Squeel's functionality by enabling core
27
33
  extensions for hashes or symbols, or aliasing some predicates, you can
28
34
  create a sample initializer with:
29
35
 
30
- rails g squeel:initializer
36
+ ```sh
37
+ $ rails g squeel:initializer
38
+ ```
31
39
 
32
40
  ## The Squeel Query DSL
33
41
 
@@ -63,8 +71,10 @@ Stubs are, for most intents and purposes, just like Symbols in a normal call to
63
71
  `Relation#where` (note the need for doubling up on the curly braces here, the first ones
64
72
  start the block, the second are the hash braces):
65
73
 
66
- Person.where{{name => 'Ernie'}}
67
- => SELECT "people".* FROM "people" WHERE "people"."name" = 'Ernie'
74
+ ```ruby
75
+ Person.where{{name => 'Ernie'}}
76
+ # => SELECT "people".* FROM "people" WHERE "people"."name" = 'Ernie'
77
+ ```
68
78
 
69
79
  You normally wouldn't bother using the DSL in this case, as a simple hash would
70
80
  suffice. However, stubs serve as a building block for keypaths, and keypaths are
@@ -76,29 +86,35 @@ A Squeel keypath is essentially a more concise and readable alternative to a
76
86
  deeply nested hash. For instance, in standard Active Record, you might join several
77
87
  associations like this to perform a query:
78
88
 
79
- Person.joins(:articles => {:comments => :person})
80
- => SELECT "people".* FROM "people"
81
- INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
82
- INNER JOIN "comments" ON "comments"."article_id" = "articles"."id"
83
- INNER JOIN "people" "people_comments" ON "people_comments"."id" = "comments"."person_id"
89
+ ```ruby
90
+ Person.joins(:articles => {:comments => :person})
91
+ # => SELECT "people".* FROM "people"
92
+ # INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
93
+ # INNER JOIN "comments" ON "comments"."article_id" = "articles"."id"
94
+ # INNER JOIN "people" "people_comments" ON "people_comments"."id" = "comments"."person_id"
95
+ ```
84
96
 
85
97
  With a keypath, this would look like:
86
98
 
87
- Person.joins{articles.comments.person}
99
+ ```ruby
100
+ Person.joins{articles.comments.person}
101
+ ```
88
102
 
89
103
  A keypath can exist in the context of a hash, and is normally interpreted relative to
90
104
  the current level of nesting. It can be forced into an "absolute" path by anchoring it with
91
105
  a ~, like:
92
106
 
93
- ~articles.comments.person
107
+ ```ruby
108
+ ~articles.comments.person
109
+ ```
94
110
 
95
111
  This isn't quite so useful in the typical hash context, but can be very useful when it comes
96
112
  to interpreting functions and the like. We'll cover those later.
97
113
 
98
114
  ### Predicates
99
115
 
100
- All of the ARel "predication" methods can be accessed inside the Squeel DSL, via
101
- their method name, an alias, or an an operator, to create ARel predicates, which are
116
+ All of the Arel "predication" methods can be accessed inside the Squeel DSL, via
117
+ their method name, an alias, or an an operator, to create Arel predicates, which are
102
118
  used in `WHERE` or `HAVING` clauses.
103
119
 
104
120
  <table>
@@ -172,34 +188,44 @@ used in `WHERE` or `HAVING` clauses.
172
188
 
173
189
  Let's say we want to generate this simple query:
174
190
 
175
- SELECT "people".* FROM people WHERE "people"."name" = 'Joe Blow'
191
+ ```
192
+ SELECT "people".* FROM people WHERE "people"."name" = 'Joe Blow'
193
+ ```
176
194
 
177
195
  All of the following will generate the above SQL:
178
196
 
179
- Person.where(:name => 'Joe Blow')
180
- Person.where{{name => 'Joe Blow'}}
181
- Person.where{{name.eq => 'Joe Blow'}}
182
- Person.where{name.eq 'Joe Blow'}
183
- Person.where{name == 'Joe Blow'}
184
-
197
+ ```ruby
198
+ Person.where(:name => 'Joe Blow')
199
+ Person.where{{name => 'Joe Blow'}}
200
+ Person.where{{name.eq => 'Joe Blow'}}
201
+ Person.where{name.eq 'Joe Blow'}
202
+ Person.where{name == 'Joe Blow'}
203
+ ```
204
+
185
205
  Not a very exciting example since equality is handled just fine via the
186
206
  first example in standard Active Record. But consider the following query:
187
207
 
188
- SELECT "people".* FROM people
189
- WHERE ("people"."name" LIKE 'Ernie%' AND "people"."salary" < 50000)
190
- OR ("people"."name" LIKE 'Joe%' AND "people"."salary" > 100000)
191
-
208
+ ```
209
+ SELECT "people".* FROM people
210
+ WHERE ("people"."name" LIKE 'Ernie%' AND "people"."salary" < 50000)
211
+ OR ("people"."name" LIKE 'Joe%' AND "people"."salary" > 100000)
212
+ ```
213
+
192
214
  To do this with standard Active Record, we'd do something like:
193
215
 
194
- Person.where(
195
- '(name LIKE ? AND salary < ?) OR (name LIKE ? AND salary > ?)',
196
- 'Ernie%', 50000, 'Joe%', 100000
197
- )
198
-
216
+ ```ruby
217
+ Person.where(
218
+ '(name LIKE ? AND salary < ?) OR (name LIKE ? AND salary > ?)',
219
+ 'Ernie%', 50000, 'Joe%', 100000
220
+ )
221
+ ```
222
+
199
223
  With Squeel:
200
224
 
201
- Person.where{(name =~ 'Ernie%') & (salary < 50000) | (name =~ 'Joe%') & (salary > 100000)}
202
-
225
+ ```ruby
226
+ Person.where{(name =~ 'Ernie%') & (salary < 50000) | (name =~ 'Joe%') & (salary > 100000)}
227
+ ```
228
+
203
229
  Here, we're using `&` and `|` to generate `AND` and `OR`, respectively.
204
230
 
205
231
  There are two obvious but important differences between these two code samples, and
@@ -209,7 +235,7 @@ both of them have to do with *context*.
209
235
  first be considered, then we must cross-reference the values to be substituted
210
236
  with their placeholders. This carries with it a small but perceptible (and
211
237
  annoying!) context shift during which we stop thinking about the comparison being
212
- performed, and instead play "count the arguments", or, in the case of
238
+ performed, and instead play "count the arguments", or, in the case of
213
239
  named/hash interpolations, "find the word". The Squeel syntax places
214
240
  both sides of each comparison in proximity to one another, allowing us to
215
241
  focus on what our code is doing.
@@ -228,12 +254,15 @@ our intentions more clear, on the first read-through. And if we don't like the
228
254
  way that the existing predications read, we can create our own aliases in a Squeel
229
255
  configure block:
230
256
 
231
- Squeel.configure do |config|
232
- config.alias_predicate :is_less_than, :lt
233
- end
234
-
235
- Person.where{salary.is_less_than 50000}.to_sql
236
- # => SELECT "people".* FROM "people" WHERE "people"."salary" < 50000
257
+ ```ruby
258
+ Squeel.configure do |config|
259
+ config.alias_predicate :is_less_than, :lt
260
+ end
261
+ ```
262
+ ```ruby
263
+ Person.where{salary.is_less_than 50000}.to_sql
264
+ # => SELECT "people".* FROM "people" WHERE "people"."salary" < 50000
265
+ ```
237
266
 
238
267
  And while we're on the topic of helping you make your code more expressive...
239
268
 
@@ -241,20 +270,26 @@ And while we're on the topic of helping you make your code more expressive...
241
270
 
242
271
  Let's say you want to check if a Person has a name like one of several possibilities.
243
272
 
244
- names = ['Ernie%', 'Joe%', 'Mary%']
245
- Person.where('name LIKE ? OR name LIKE ? OR name LIKE ?', *names)
273
+ ```ruby
274
+ names = ['Ernie%', 'Joe%', 'Mary%']
275
+ Person.where('name LIKE ? OR name LIKE ? OR name LIKE ?', *names)
276
+ ```
246
277
 
247
278
  But you're smart, and you know that you might want to check more or less than
248
279
  3 names, so you make your query flexible:
249
280
 
250
- Person.where((['name LIKE ?'] * names.size).join(' OR '), *names)
281
+ ```ruby
282
+ Person.where((['name LIKE ?'] * names.size).join(' OR '), *names)
283
+ ```
251
284
 
252
285
  Yeah... that's readable, all right. How about:
253
286
 
254
- Person.where{name.like_any names}
255
- # => SELECT "people".* FROM "people"
256
- WHERE (("people"."name" LIKE 'Ernie%' OR "people"."name" LIKE 'Joe%' OR "people"."name" LIKE 'Mary%'))
257
-
287
+ ```ruby
288
+ Person.where{name.like_any names}
289
+ # => SELECT "people".* FROM "people"
290
+ # WHERE (("people"."name" LIKE 'Ernie%' OR "people"."name" LIKE 'Joe%' OR "people"."name" LIKE 'Mary%'))
291
+ ```
292
+
258
293
  I'm not sure about you, but I much prefer the latter. In short, you can add `_any` or
259
294
  `_all` to any predicate method, and it would do what you expect, when given an array of
260
295
  possibilities to compare against.
@@ -265,57 +300,69 @@ Sifters are like little snippets of conditions that take parameters. Let's say t
265
300
  have a model called Article, and you often want to query for articles that contain a
266
301
  string in the title or body. So you write a scope:
267
302
 
268
- def self.title_or_body_contains(string)
269
- where{title.matches("%#{string}%") | body.matches("%#{string}%")}
270
- end
303
+ ```ruby
304
+ def self.title_or_body_contains(string)
305
+ where{title.matches("%#{string}%") | body.matches("%#{string}%")}
306
+ end
307
+ ```
271
308
 
272
309
  But then you want to query for people who wrote an article that matches these conditions,
273
310
  but the scope only works against the model where it was defined. So instead, you write a
274
311
  sifter:
275
312
 
276
- class Article < ActiveRecord::Base
277
- sifter :title_or_body_contains do |string|
278
- title.matches("%#{string}%") | body.matches("%#{string}%")
279
- end
280
- end
313
+ ```ruby
314
+ class Article < ActiveRecord::Base
315
+ sifter :title_or_body_contains do |string|
316
+ title.matches("%#{string}%") | body.matches("%#{string}%")
317
+ end
318
+ end
319
+ ```
281
320
 
282
321
  Now you can write...
283
322
 
284
- Article.where{sift :title_or_body_contains, 'awesome'}
285
- => SELECT "articles".* FROM "articles"
286
- WHERE ((
287
- "articles"."title" LIKE '%awesome%'
288
- OR "articles"."body" LIKE '%awesome%'
289
- ))
323
+ ```ruby
324
+ Article.where{sift :title_or_body_contains, 'awesome'}
325
+ # => SELECT "articles".* FROM "articles"
326
+ # WHERE ((
327
+ # "articles"."title" LIKE '%awesome%'
328
+ # OR "articles"."body" LIKE '%awesome%'
329
+ # ))
330
+ ```
290
331
 
291
332
  ... or ...
292
333
 
293
- Person.joins(:articles).
294
- where{
295
- {articles => sift(:title_or_body_contains, 'awesome')}
296
- }
297
- # => SELECT "people".* FROM "people"
298
- INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
299
- WHERE ((
300
- "articles"."title" LIKE '%awesome%'
301
- OR "articles"."body" LIKE '%awesome%'
302
- ))
334
+ ```ruby
335
+ Person.joins(:articles).
336
+ where{
337
+ {articles => sift(:title_or_body_contains, 'awesome')}
338
+ }
339
+ # => SELECT "people".* FROM "people"
340
+ # INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
341
+ # WHERE ((
342
+ # "articles"."title" LIKE '%awesome%'
343
+ # OR "articles"."body" LIKE '%awesome%'
344
+ # ))
345
+ ```
303
346
 
304
347
  Or, you can just modify your previous scope, changing `where` to `squeel`:
305
348
 
306
- def self.title_or_body_contains(string)
307
- squeel{title.matches("%#{string}%") | body.matches("%#{string}%")}
308
- end
349
+ ```ruby
350
+ def self.title_or_body_contains(string)
351
+ squeel{title.matches("%#{string}%") | body.matches("%#{string}%")}
352
+ end
353
+ ```
309
354
 
310
355
  ### Subqueries
311
356
 
312
357
  You can supply an `ActiveRecord::Relation` as a value for a predicate in order to use
313
358
  a subquery. So, for example:
314
359
 
315
- awesome_people = Person.where{awesome == true}
316
- Article.where{author_id.in(awesome_people.select{id})}
317
- # => SELECT "articles".* FROM "articles"
318
- WHERE "articles"."author_id" IN (SELECT "people"."id" FROM "people" WHERE "people"."awesome" = 't')
360
+ ```ruby
361
+ awesome_people = Person.where{awesome == true}
362
+ Article.where{author_id.in(awesome_people.select{id})}
363
+ # => SELECT "articles".* FROM "articles"
364
+ # WHERE "articles"."author_id" IN (SELECT "people"."id" FROM "people" WHERE "people"."awesome" = 't')
365
+ ```
319
366
 
320
367
  ### Joins
321
368
 
@@ -323,40 +370,46 @@ Squeel adds a couple of enhancements to joins. First, keypaths can be used as sh
323
370
  nested association joins. Second, you can specify join types (inner and outer), and a class
324
371
  in the case of a polymorphic belongs_to relationship.
325
372
 
326
- Person.joins{articles.outer}
327
- => SELECT "people".* FROM "people"
328
- LEFT OUTER JOIN "articles" ON "articles"."person_id" = "people"."id"
329
- Note.joins{notable(Person).outer}
330
- => SELECT "notes".* FROM "notes"
331
- LEFT OUTER JOIN "people"
332
- ON "people"."id" = "notes"."notable_id"
333
- AND "notes"."notable_type" = 'Person'
373
+ ```ruby
374
+ Person.joins{articles.outer}
375
+ # => SELECT "people".* FROM "people"
376
+ # LEFT OUTER JOIN "articles" ON "articles"."person_id" = "people"."id"
377
+ Note.joins{notable(Person).outer}
378
+ # => SELECT "notes".* FROM "notes"
379
+ # LEFT OUTER JOIN "people"
380
+ # ON "people"."id" = "notes"."notable_id"
381
+ # AND "notes"."notable_type" = 'Person'
382
+ ```
334
383
 
335
384
  These can also be used inside keypaths:
336
385
 
337
- Note.joins{notable(Person).articles}
338
- => SELECT "notes".* FROM "notes"
339
- INNER JOIN "people" ON "people"."id" = "notes"."notable_id"
340
- AND "notes"."notable_type" = 'Person'
341
- INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
342
-
386
+ ```ruby
387
+ Note.joins{notable(Person).articles}
388
+ # => SELECT "notes".* FROM "notes"
389
+ # INNER JOIN "people" ON "people"."id" = "notes"."notable_id"
390
+ # AND "notes"."notable_type" = 'Person'
391
+ # INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
392
+ ```
393
+
343
394
  You can refer to these associations when constructing other parts of your query, and
344
395
  they'll be automatically mapped to the proper table or table alias This is most noticeable
345
396
  when using self-referential associations:
346
397
 
347
- Person.joins{children.parent.children}.
348
- where{
349
- (children.name.like 'Ernie%') |
350
- (children.parent.name.like 'Ernie%') |
351
- (children.parent.children.name.like 'Ernie%')
352
- }
353
- => SELECT "people".* FROM "people"
354
- INNER JOIN "people" "children_people" ON "children_people"."parent_id" = "people"."id"
355
- INNER JOIN "people" "parents_people" ON "parents_people"."id" = "children_people"."parent_id"
356
- INNER JOIN "people" "children_people_2" ON "children_people_2"."parent_id" = "parents_people"."id"
357
- WHERE ((("children_people"."name" LIKE 'Ernie%'
358
- OR "parents_people"."name" LIKE 'Ernie%')
359
- OR "children_people_2"."name" LIKE 'Ernie%'))
398
+ ```ruby
399
+ Person.joins{children.parent.children}.
400
+ where{
401
+ (children.name.like 'Ernie%') |
402
+ (children.parent.name.like 'Ernie%') |
403
+ (children.parent.children.name.like 'Ernie%')
404
+ }
405
+ # => SELECT "people".* FROM "people"
406
+ # INNER JOIN "people" "children_people" ON "children_people"."parent_id" = "people"."id"
407
+ # INNER JOIN "people" "parents_people" ON "parents_people"."id" = "children_people"."parent_id"
408
+ # INNER JOIN "people" "children_people_2" ON "children_people_2"."parent_id" = "parents_people"."id"
409
+ # WHERE ((("children_people"."name" LIKE 'Ernie%'
410
+ # OR "parents_people"."name" LIKE 'Ernie%')
411
+ # OR "children_people_2"."name" LIKE 'Ernie%'))
412
+ ```
360
413
 
361
414
  Keypaths were used here for clarity, but nested hashes would work just as well.
362
415
 
@@ -364,33 +417,41 @@ Keypaths were used here for clarity, but nested hashes would work just as well.
364
417
 
365
418
  You can call SQL functions just like you would call a method in Ruby...
366
419
 
367
- Person.select{coalesce(name, '<no name given>')}
368
- => SELECT coalesce("people"."name", '<no name given>') FROM "people"
420
+ ```ruby
421
+ Person.select{coalesce(name, '<no name given>')}
422
+ # => SELECT coalesce("people"."name", '<no name given>') FROM "people"
423
+ ```
369
424
 
370
425
  ...and you can easily give it an alias:
371
426
 
372
- person = Person.select{
373
- coalesce(name, '<no name given>').as(name_with_default)
374
- }.first
375
- person.name_with_default # name or <no name given>, depending on data
427
+ ```ruby
428
+ person = Person.select{
429
+ coalesce(name, '<no name given>').as(name_with_default)
430
+ }.first
431
+ person.name_with_default # name or <no name given>, depending on data
432
+ ```
376
433
 
377
434
  When you use a stub, symbol, or keypath inside a function call, it'll be interpreted relative to
378
435
  its place inside any nested associations:
379
436
 
380
- Person.joins{articles}.group{articles.title}.having{{articles => {max(id) => id}}}
381
- => SELECT "people".* FROM "people"
382
- INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
383
- GROUP BY "articles"."title"
384
- HAVING max("articles"."id") = "articles"."id"
385
-
437
+ ```ruby
438
+ Person.joins{articles}.group{articles.title}.having{{articles => {max(id) => id}}}
439
+ # => SELECT "people".* FROM "people"
440
+ # INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
441
+ # GROUP BY "articles"."title"
442
+ # HAVING max("articles"."id") = "articles"."id"
443
+ ```
444
+
386
445
  If you want to use an attribute from a different branch of the hierarchy, use an absolute
387
446
  keypath (~) as done here:
388
447
 
389
- Person.joins{articles}.group{articles.title}.having{{articles => {max(~id) => id}}}
390
- => SELECT "people".* FROM "people"
391
- INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
392
- GROUP BY "articles"."title"
393
- HAVING max("people"."id") = "articles"."id"
448
+ ```ruby
449
+ Person.joins{articles}.group{articles.title}.having{{articles => {max(~id) => id}}}
450
+ # => SELECT "people".* FROM "people"
451
+ # INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
452
+ # GROUP BY "articles"."title"
453
+ # HAVING max("people"."id") = "articles"."id"
454
+ ```
394
455
 
395
456
  ### SQL Operators
396
457
 
@@ -398,13 +459,15 @@ You can use the standard mathematical operators (`+`, `-`, `*`, `/`) inside the
398
459
  specify operators in the resulting SQL, or the `op` method to specify another
399
460
  custom operator, such as the standard SQL concatenation operator, `||`:
400
461
 
401
- p = Person.select{name.op('||', '-diddly').as(flanderized_name)}.first
402
- p.flanderized_name
403
- => "Aric Smith-diddly"
462
+ ```ruby
463
+ p = Person.select{name.op('||', '-diddly').as(flanderized_name)}.first
464
+ p.flanderized_name
465
+ # => "Aric Smith-diddly"
466
+ ```
404
467
 
405
468
  As you can see, just like functions, these operations can be given aliases.
406
469
 
407
- ## Compatibility with Active Record
470
+ ## Compatibility with Active Record
408
471
 
409
472
  Most of the new functionality provided by Squeel is accessed with the new block-style `where{}`
410
473
  syntax.
@@ -424,15 +487,21 @@ the name of a **column** instead of simply treating the symbol as a **string lit
424
487
 
425
488
  For example, this query:
426
489
 
427
- Person.where(:first_name => :last_name)
490
+ ```ruby
491
+ Person.where(:first_name => :last_name)
492
+ ```
428
493
 
429
494
  produces this SQL query in plain Active Record:
430
495
 
431
- SELECT people.* FROM people WHERE people.first_name = 'last_name'.
496
+ ```
497
+ SELECT people.* FROM people WHERE people.first_name = 'last_name'.
498
+ ```
432
499
 
433
500
  but produces this SQL query if you are using Squeel:
434
501
 
435
- SELECT people.* FROM people WHERE people.first_name = people.last_name
502
+ ```
503
+ SELECT people.* FROM people WHERE people.first_name = people.last_name
504
+ ```
436
505
 
437
506
  Note that this new behavior applies to the plain `where()`-style expressions in addition to the new
438
507
  `where{}` Squeel style.
@@ -440,13 +509,17 @@ Note that this new behavior applies to the plain `where()`-style expressions in
440
509
  In order for your existing `where()` clauses with symbols to continue to behave the same, you
441
510
  **must** change the symbols into strings. These scopes, for example:
442
511
 
443
- scope :active, where(:state => :active)
444
- scope :in_state, lambda {|state| where(:state => state) }
512
+ ```ruby
513
+ scope :active, where(:state => :active)
514
+ scope :in_state, lambda {|state| where(:state => state) }
515
+ ```
445
516
 
446
517
  should be changed to this:
447
518
 
448
- scope :active, where(:state => 'active')
449
- scope :in_state, lambda {|state| where(:state => state.to_s) }
519
+ ```ruby
520
+ scope :active, where(:state => 'active')
521
+ scope :in_state, lambda {|state| where(:state => state.to_s) }
522
+ ```
450
523
 
451
524
  For further information, see
452
525
  [this post to the Rails list](https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-core/NQJJzZ7R7S0),
@@ -459,18 +532,21 @@ the [Active Record guides](http://edgeguides.rubyonrails.org/active_record_query
459
532
  ## Compatibility with MetaWhere
460
533
 
461
534
  While the Squeel DSL is the preferred way to access advanced query functionality, you can
462
- still enable methods on symbols to access ARel predications in a similar manner to MetaWhere:
463
-
464
- Squeel.configure do |config|
465
- config.load_core_extensions :symbol
466
- end
467
-
468
- Person.joins(:articles => :comments).
469
- where(:articles => {:comments => {:body.matches => 'Hello!'}})
470
- SELECT "people".* FROM "people"
471
- INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
472
- INNER JOIN "comments" ON "comments"."article_id" = "articles"."id"
473
- WHERE "comments"."body" LIKE 'Hello!'
535
+ still enable methods on symbols to access Arel predications in a similar manner to MetaWhere:
536
+
537
+ ```ruby
538
+ Squeel.configure do |config|
539
+ config.load_core_extensions :symbol
540
+ end
541
+ ```
542
+ ```ruby
543
+ Person.joins(:articles => :comments).
544
+ where(:articles => {:comments => {:body.matches => 'Hello!'}})
545
+ # => SELECT "people".* FROM "people"
546
+ # INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
547
+ # INNER JOIN "comments" ON "comments"."article_id" = "articles"."id"
548
+ # WHERE "comments"."body" LIKE 'Hello!'
549
+ ```
474
550
 
475
551
  This should help to smooth over the transition to the new DSL.
476
552