squeel 0.5.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/.yardopts +3 -0
  2. data/Gemfile +8 -3
  3. data/README.md +368 -0
  4. data/lib/core_ext/hash.rb +8 -8
  5. data/lib/core_ext/symbol.rb +7 -6
  6. data/lib/squeel.rb +2 -0
  7. data/lib/squeel/adapters/active_record.rb +25 -20
  8. data/lib/squeel/adapters/active_record/3.0/compat.rb +1 -2
  9. data/lib/squeel/adapters/active_record/3.0/context.rb +6 -7
  10. data/lib/squeel/adapters/active_record/3.0/join_dependency.rb +5 -5
  11. data/lib/squeel/adapters/active_record/context.rb +6 -7
  12. data/lib/squeel/adapters/active_record/join_dependency.rb +5 -5
  13. data/lib/squeel/configuration.rb +29 -0
  14. data/lib/squeel/constants.rb +1 -0
  15. data/lib/squeel/context.rb +36 -7
  16. data/lib/squeel/dsl.rb +57 -2
  17. data/lib/squeel/nodes.rb +6 -0
  18. data/lib/squeel/nodes/and.rb +1 -0
  19. data/lib/squeel/nodes/binary.rb +11 -2
  20. data/lib/squeel/nodes/function.rb +30 -48
  21. data/lib/squeel/nodes/join.rb +56 -12
  22. data/lib/squeel/nodes/key_path.rb +68 -2
  23. data/lib/squeel/nodes/nary.rb +12 -2
  24. data/lib/squeel/nodes/not.rb +1 -0
  25. data/lib/squeel/nodes/operation.rb +9 -0
  26. data/lib/squeel/nodes/operators.rb +16 -0
  27. data/lib/squeel/nodes/or.rb +1 -0
  28. data/lib/squeel/nodes/order.rb +19 -1
  29. data/lib/squeel/nodes/predicate.rb +25 -3
  30. data/lib/squeel/nodes/predicate_operators.rb +12 -0
  31. data/lib/squeel/nodes/stub.rb +55 -48
  32. data/lib/squeel/nodes/unary.rb +7 -1
  33. data/lib/squeel/predicate_methods.rb +2 -10
  34. data/lib/squeel/version.rb +1 -1
  35. data/lib/squeel/visitors/attribute_visitor.rb +80 -4
  36. data/lib/squeel/visitors/base.rb +70 -4
  37. data/lib/squeel/visitors/predicate_visitor.rb +28 -9
  38. data/lib/squeel/visitors/symbol_visitor.rb +1 -1
  39. data/spec/core_ext/symbol_spec.rb +2 -2
  40. data/spec/spec_helper.rb +6 -1
  41. data/spec/squeel/adapters/active_record/context_spec.rb +0 -7
  42. data/spec/squeel/adapters/active_record/relation_spec.rb +27 -0
  43. data/spec/squeel/dsl_spec.rb +20 -1
  44. data/spec/squeel/nodes/join_spec.rb +11 -4
  45. data/spec/squeel/nodes/key_path_spec.rb +1 -1
  46. data/spec/squeel/nodes/predicate_spec.rb +0 -42
  47. data/spec/squeel/nodes/stub_spec.rb +9 -8
  48. data/spec/squeel/visitors/predicate_visitor_spec.rb +34 -9
  49. data/squeel.gemspec +6 -9
  50. metadata +8 -10
  51. data/README.rdoc +0 -117
  52. data/lib/squeel/predicate_methods/function.rb +0 -9
  53. data/lib/squeel/predicate_methods/predicate.rb +0 -11
  54. data/lib/squeel/predicate_methods/stub.rb +0 -9
  55. data/lib/squeel/predicate_methods/symbol.rb +0 -9
@@ -0,0 +1,3 @@
1
+ --main README.md
2
+ --private
3
+ --exclude compat
data/Gemfile CHANGED
@@ -1,8 +1,13 @@
1
1
  source "http://rubygems.org"
2
2
  gemspec
3
3
 
4
- gem 'arel', :git => 'git://github.com/rails/arel.git'
5
- git 'git://github.com/rails/rails.git' do
4
+ if ENV['RAILS_VERSION'] == 'release'
6
5
  gem 'activesupport'
7
6
  gem 'activerecord'
8
- end
7
+ else
8
+ gem 'arel', :git => 'git://github.com/rails/arel.git'
9
+ git 'git://github.com/rails/rails.git' do
10
+ gem 'activesupport'
11
+ gem 'activerecord'
12
+ end
13
+ end
@@ -0,0 +1,368 @@
1
+ # Squeel
2
+
3
+ Squeel is a rewrite of [MetaWhere](http://metautonomo.us/projects/metawhere).
4
+
5
+ ## Getting started
6
+
7
+ In your Gemfile:
8
+
9
+ gem "squeel" # Last officially released gem
10
+ # gem "squeel", :git => "git://github.com/ernie/squeel.git" # Track git repo
11
+
12
+ In an intitializer:
13
+
14
+ Squeel.configure do |config|
15
+ # To load hash extensions (to allow for AND (&), OR (|), and NOT (-) against
16
+ # hashes of conditions)
17
+ config.load_core_extensions :hash
18
+
19
+ # To load symbol extensions (for a subset of the old MetaWhere functionality,
20
+ # via ARel predicate methods on Symbols: :name.matches, etc)
21
+ # config.load_core_extensions :symbol
22
+
23
+ # To load both hash and symbol extensions
24
+ # config.load_core_extensions :hash, :symbol
25
+ end
26
+
27
+ ## The Squeel Query DSL
28
+
29
+ Squeel enhances the normal ActiveRecord query methods by enabling them to accept
30
+ blocks. Inside a block, the Squeel query DSL can be used. Note the use of curly braces
31
+ in these examples instead of parentheses. `{}` denotes a Squeel DSL query.
32
+
33
+ Stubs and keypaths are the two primary building blocks used in a Squeel DSL query, so
34
+ before we go on, let's take a look at them. Most of the other examples that follow will
35
+ be based on this "symbol-less" syntax, so it might look a bit foreign otherwise.
36
+
37
+ ### Stubs
38
+
39
+ Stubs are, for most intents and purposes, just like Symbols in a normal call to
40
+ `Relation#where` (note the need for doubling up on the curly braces here, the first ones
41
+ start the block, the second are the hash braces):
42
+
43
+ Person.where{{name => 'Ernie'}}
44
+ => SELECT "people".* FROM "people" WHERE "people"."name" = 'Ernie'
45
+
46
+ You normally wouldn't bother using the DSL in this case, as a simple hash would
47
+ suffice. However, stubs serve as a building block for keypaths, and keypaths are
48
+ very handy.
49
+
50
+ ### KeyPaths
51
+
52
+ A Squeel keypath is essentially a more concise and readable alternative to a
53
+ deeply nested hash. For instance, in standard ActiveRecord, you might join several
54
+ associations like this to perform a query:
55
+
56
+ Person.joins(:articles => {:comments => :person})
57
+ => SELECT "people".* FROM "people"
58
+ INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
59
+ INNER JOIN "comments" ON "comments"."article_id" = "articles"."id"
60
+ INNER JOIN "people" "people_comments" ON "people_comments"."id" = "comments"."person_id"
61
+
62
+ With a keypath, this would look like:
63
+
64
+ Person.joins{articles.comments.person}
65
+
66
+ A keypath can exist in the context of a hash, and is normally interpreted relative to
67
+ the current level of nesting. It can be forced into an "absolute" path by anchoring it with
68
+ a ~, like:
69
+
70
+ ~articles.comments.person
71
+
72
+ This isn't quite so useful in the typical hash context, but can be very useful when it comes
73
+ to interpreting functions and the like. We'll cover those later.
74
+
75
+ ### Predicates
76
+
77
+ All of the ARel "predication" methods can be accessed inside the Squeel DSL, via
78
+ their method name, an alias, or an an operator, to create ARel predicates, which are
79
+ used in `WHERE` or `HAVING` clauses.
80
+
81
+ <table>
82
+ <tr>
83
+ <th>SQL</th>
84
+ <th>Predication</th>
85
+ <th>Operator</th>
86
+ <th>Alias</th>
87
+ </tr>
88
+ <tr>
89
+ <td>=</td>
90
+ <td>eq</td>
91
+ <td>==</td>
92
+ <td></td>
93
+ </tr>
94
+ <tr>
95
+ <td>!=</td>
96
+ <td>not_eq</td>
97
+ <td>!=</td>
98
+ <td></td>
99
+ </tr>
100
+ <tr>
101
+ <td>LIKE</td>
102
+ <td>matches</td>
103
+ <td>=~</td>
104
+ <td>like</td>
105
+ </tr>
106
+ <tr>
107
+ <td>NOT LIKE</td>
108
+ <td>does_not_match</td>
109
+ <td>!~</td>
110
+ <td>not_like</td>
111
+ </tr>
112
+ <tr>
113
+ <td>&lt;</td>
114
+ <td>lt</td>
115
+ <td>&lt;</td>
116
+ <td></td>
117
+ </tr>
118
+ <tr>
119
+ <td>&lt;=</td>
120
+ <td>lteq</td>
121
+ <td>&lt;=</td>
122
+ <td>lte</td>
123
+ </tr>
124
+ <tr>
125
+ <td>></td>
126
+ <td>gt</td>
127
+ <td>></td>
128
+ <td></td>
129
+ </tr>
130
+ <tr>
131
+ <td>>=</td>
132
+ <td>gteq</td>
133
+ <td>>=</td>
134
+ <td>gte</td>
135
+ </tr>
136
+ <tr>
137
+ <td>IN</td>
138
+ <td>in</td>
139
+ <td>>></td>
140
+ <td></td>
141
+ </tr>
142
+ <tr>
143
+ <td>NOT IN</td>
144
+ <td>not_in</td>
145
+ <td>&lt;&lt;</td>
146
+ <td></td>
147
+ </tr>
148
+ </table>
149
+
150
+ Let's say we want to generate this simple query:
151
+
152
+ SELECT "people".* FROM people WHERE "people"."name" = 'Joe Blow'
153
+
154
+ All of the following will generate the above SQL:
155
+
156
+ Person.where(:name => 'Joe Blow')
157
+ Person.where{{name => 'Joe Blow'}}
158
+ Person.where{{name.eq => 'Joe Blow'}}
159
+ Person.where{name.eq 'Joe Blow'}
160
+ Person.where{name == 'Joe Blow'}
161
+
162
+ Not a very exciting example since equality is handled just fine via the
163
+ first example in standard ActiveRecord. But consider the following query:
164
+
165
+ SELECT "people".* FROM people
166
+ WHERE ("people"."name" LIKE 'Ernie%' AND "people"."salary" < 50000)
167
+ OR ("people"."name" LIKE 'Joe%' AND "people"."salary" > 100000)
168
+
169
+ To do this with standard ActiveRecord, we'd do something like:
170
+
171
+ Person.where(
172
+ '(name LIKE ? AND salary < ?) OR (name LIKE ? AND salary > ?)',
173
+ 'Ernie%', 50000, 'Joe%', 100000
174
+ )
175
+
176
+ With Squeel:
177
+
178
+ Person.where{(name =~ 'Ernie%') & (salary < 50000) | (name =~ 'Joe%') & (salary > 100000)}
179
+
180
+ Here, we're using `&` and `|` to generate `AND` and `OR`, respectively.
181
+
182
+ There are two obvious but important differences between these two code samples, and
183
+ both of them have to do with *context*.
184
+
185
+ 1. To read code with SQL interpolation, the structure of the SQL query must
186
+ first be considered, then we must cross-reference the values to be substituted
187
+ with their placeholders. This carries with it a small but perceptible (and
188
+ annoying!) context shift during which we stop thinking about the comparison being
189
+ performed, and instead play "count the arguments", or, in the case of
190
+ named/hash interpolations, "find the word". The Squeel syntax places
191
+ both sides of each comparison in proximity to one another, allowing us to
192
+ focus on what our code is doing.
193
+
194
+ 2. In the first example, we're starting off with Ruby, switching context to SQL,
195
+ and then back to Ruby, and while we spend time in SQL-land, we're stuck with
196
+ SQL syntax, whether or not it's the best way to express what we're trying to do.
197
+ With Squeel, we're writing Ruby from start to finish. And with Ruby syntax comes
198
+ flexibility to express the query in the way we see fit.
199
+
200
+ ### Predicate aliases
201
+
202
+ That last bit is important. We can mix and match predicate methods with operators
203
+ and take advantage of Ruby's operator precedence or parenthetical grouping to make
204
+ our intentions more clear, on the first read-through. And if we don't like the
205
+ way that the existing predications read, we can create our own aliases in a Squeel
206
+ configure block:
207
+
208
+ Squeel.configure do |config|
209
+ config.alias_predicate :is_less_than, :lt
210
+ end
211
+
212
+ Person.where{salary.is_less_than 50000}.to_sql
213
+ # => SELECT "people".* FROM "people" WHERE "people"."salary" < 50000
214
+
215
+ And while we're on the topic of helping you make your code more expressive...
216
+
217
+ ### Compound conditions
218
+
219
+ Let's say you want to check if a Person has a name like one of several possibilities.
220
+
221
+ names = ['Ernie%', 'Joe%', 'Mary%']
222
+ Person.where('name LIKE ? OR name LIKE ? OR name LIKE ?', *names)
223
+
224
+ But you're smart, and you know that you might want to check more or less than
225
+ 3 names, so you make your query flexible:
226
+
227
+ Person.where((['name LIKE ?'] * names.size).join(' OR '), *names)
228
+
229
+ Yeah... that's readable, all right. How about:
230
+
231
+ Person.where{name.like_any names}
232
+ # => SELECT "people".* FROM "people"
233
+ WHERE (("people"."name" LIKE 'Ernie%' OR "people"."name" LIKE 'Joe%' OR "people"."name" LIKE 'Mary%'))
234
+
235
+ I'm not sure about you, but I much prefer the latter. In short, you can add `_any` or
236
+ `_all` to any predicate method, and it would do what you expect, when given an array of
237
+ possibilities to compare against.
238
+
239
+ ### Subqueries
240
+
241
+ You can supply an `ActiveRecord::Relation` as a value for a predicate in order to use
242
+ a subquery. So, for example:
243
+
244
+ awesome_people = Person.where{awesome == true}
245
+ Article.where{author_id.in(awesome_people.select{id})}
246
+ # => SELECT "articles".* FROM "articles"
247
+ WHERE "articles"."author_id" IN (SELECT "people"."id" FROM "people" WHERE "people"."awesome" = 't')
248
+
249
+ ### Joins
250
+
251
+ Squeel adds a couple of enhancements to joins. First, keypaths can be used as shorthand for
252
+ nested association joins. Second, you can specify join types (inner and outer), and a class
253
+ in the case of a polymorphic belongs_to relationship.
254
+
255
+ Person.joins{articles.outer}
256
+ => SELECT "people".* FROM "people"
257
+ LEFT OUTER JOIN "articles" ON "articles"."person_id" = "people"."id"
258
+ Note.joins{notable(Person).outer}
259
+ => SELECT "notes".* FROM "notes"
260
+ LEFT OUTER JOIN "people"
261
+ ON "people"."id" = "notes"."notable_id"
262
+ AND "notes"."notable_type" = 'Person'
263
+
264
+ These can also be used inside keypaths:
265
+
266
+ Note.joins{notable(Person).articles}
267
+ => SELECT "notes".* FROM "notes"
268
+ INNER JOIN "people" ON "people"."id" = "notes"."notable_id"
269
+ AND "notes"."notable_type" = 'Person'
270
+ INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
271
+
272
+ You can refer to these associations when constructing other parts of your query, and
273
+ they'll be automatically mapped to the proper table or table alias This is most noticeable
274
+ when using self-referential associations:
275
+
276
+ Person.joins{children.parent.children}.
277
+ where{
278
+ (children.name.like 'Ernie%') |
279
+ (children.parent.name.like 'Ernie%') |
280
+ (children.parent.children.name.like 'Ernie%')
281
+ }
282
+ => SELECT "people".* FROM "people"
283
+ INNER JOIN "people" "children_people" ON "children_people"."parent_id" = "people"."id"
284
+ INNER JOIN "people" "parents_people" ON "parents_people"."id" = "children_people"."parent_id"
285
+ INNER JOIN "people" "children_people_2" ON "children_people_2"."parent_id" = "parents_people"."id"
286
+ WHERE ((("children_people"."name" LIKE 'Ernie%'
287
+ OR "parents_people"."name" LIKE 'Ernie%')
288
+ OR "children_people_2"."name" LIKE 'Ernie%'))
289
+
290
+ Keypaths were used here for clarity, but nested hashes would work just as well.
291
+
292
+ ### Functions
293
+
294
+ You can call SQL functions just like you would call a method in Ruby...
295
+
296
+ Person.select{coalesce(name, '<no name given>')}
297
+ => SELECT coalesce("people"."name", '<no name given>') FROM "people"
298
+
299
+ ...and you can easily give it an alias:
300
+
301
+ person = Person.select{
302
+ coalesce(name, '<no name given>').as(name_with_default)
303
+ }.first
304
+ person.name_with_default # name or <no name given>, depending on data
305
+
306
+ When you use a stub, symbol, or keypath inside a function call, it'll be interpreted relative to
307
+ its place inside any nested associations:
308
+
309
+ Person.joins{articles}.group{articles.title}.having{{articles => {max(id) => id}}}
310
+ => SELECT "people".* FROM "people"
311
+ INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
312
+ GROUP BY "articles"."title"
313
+ HAVING max("articles"."id") = "articles"."id"
314
+
315
+ If you want to use an attribute from a different branch of the hierarchy, use an absolute
316
+ keypath (~) as done here:
317
+
318
+ Person.joins{articles}.group{articles.title}.having{{articles => {max(~id) => id}}}
319
+ => SELECT "people".* FROM "people"
320
+ INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
321
+ GROUP BY "articles"."title"
322
+ HAVING max("people"."id") = "articles"."id"
323
+
324
+ ### SQL Operators
325
+
326
+ You can use the standard mathematical operators (`+`, `-`, `*`, `/`) inside the Squeel DSL to
327
+ specify operators in the resulting SQL, or the `op` method to specify another
328
+ custom operator, such as the standard SQL concatenation operator, `||`:
329
+
330
+ p = Person.select{name.op('||', '-diddly').as(flanderized_name)}.first
331
+ p.flanderized_name
332
+ => "Aric Smith-diddly"
333
+
334
+ As you can see, just like functions, these operations can be given aliases.
335
+
336
+ ## Legacy compatibility
337
+
338
+ While the Squeel DSL is the preferred way to access advanced query functionality, you can
339
+ still enable methods on symbols to access ARel predications in a similar manner to MetaWhere:
340
+
341
+ Squeel.configure do |config|
342
+ config.load_core_extensions :symbol
343
+ end
344
+
345
+ Person.joins(:articles => :comments).
346
+ where(:articles => {:comments => {:body.matches => 'Hello!'}})
347
+ SELECT "people".* FROM "people"
348
+ INNER JOIN "articles" ON "articles"."person_id" = "people"."id"
349
+ INNER JOIN "comments" ON "comments"."article_id" = "articles"."id"
350
+ WHERE "comments"."body" LIKE 'Hello!'
351
+
352
+ This should help to smooth over the transition to the new DSL.
353
+
354
+ ## Contributions
355
+
356
+ If you'd like to support the continued development of Squeel, please consider
357
+ [making a donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N7QP5N3UB76ME).
358
+
359
+ To support the project in other ways:
360
+
361
+ * Use Squeel in your apps, and let me know if you encounter anything that's broken or missing.
362
+ A failing spec is awesome. A pull request is even better!
363
+ * Spread the word on Twitter, Facebook, and elsewhere if Squeel's been useful to you. The more
364
+ people who are using the project, the quicker we can find and fix bugs!
365
+
366
+ ## Copyright
367
+
368
+ Copyright &copy; 2011 [Ernie Miller](http://twitter.com/erniemiller)
@@ -1,13 +1,13 @@
1
1
  require 'squeel/nodes/predicate_operators'
2
2
 
3
+ # Hashes are "acceptable" by PredicateVisitor, so they
4
+ # can be treated like nodes for the purposes of and/or/not
5
+ # if you load these extensions.
6
+ #
7
+ # @example Load Hash extensions
8
+ # Squeel.configure do |config|
9
+ # config.load_core_extensions :hash
10
+ # end
3
11
  class Hash
4
- # Hashes are "acceptable" by PredicateVisitor, so they
5
- # can be treated like nodes for the purposes of and/or/not
6
- # if you load core extensions with:
7
- #
8
- # Squeel.configure do |config|
9
- # config.load_core_extensions :hash
10
- # end
11
-
12
12
  include Squeel::Nodes::PredicateOperators
13
13
  end
@@ -1,12 +1,13 @@
1
1
  require 'squeel/predicate_methods'
2
2
 
3
+ # These extensions to Symbol are loaded optionally, mostly to provide
4
+ # a small amount of backwards compatibility with MetaWhere.
5
+ #
6
+ # @example Load Symbol extensions
7
+ # Squeel.configure do |config|
8
+ # config.load_core_extensions :symbol
9
+ # end
3
10
  class Symbol
4
- # These extensions to Symbol are loaded optionally, with:
5
- #
6
- # Squeel.configure do |config|
7
- # config.load_core_extensions :symbol
8
- # end
9
-
10
11
  include Squeel::PredicateMethods
11
12
 
12
13
  def asc
@@ -4,6 +4,7 @@ module Squeel
4
4
 
5
5
  extend Configuration
6
6
 
7
+ # Prevent warnings on the console when doing things some might describe as "evil"
7
8
  def self.evil_things
8
9
  original_verbosity = $VERBOSE
9
10
  $VERBOSE = nil
@@ -12,6 +13,7 @@ module Squeel
12
13
  $VERBOSE = original_verbosity
13
14
  end
14
15
 
16
+ # Set up initial predicate aliases
15
17
  Constants::PREDICATE_ALIASES.each do |original, aliases|
16
18
  aliases.each do |aliaz|
17
19
  alias_predicate aliaz, original
@@ -1,23 +1,28 @@
1
- case ActiveRecord::VERSION::STRING
2
- when /^3\.0\./
3
- require 'squeel/adapters/active_record/3.0/compat'
4
- require 'squeel/adapters/active_record/3.0/relation'
5
- require 'squeel/adapters/active_record/3.0/join_dependency'
6
- require 'squeel/adapters/active_record/3.0/join_association'
7
- require 'squeel/adapters/active_record/3.0/association_preload'
8
- require 'squeel/adapters/active_record/3.0/context'
1
+ case ActiveRecord::VERSION::MAJOR
2
+ when 3
3
+ case ActiveRecord::VERSION::MINOR
4
+ when 0
5
+ require 'squeel/adapters/active_record/3.0/compat'
6
+ require 'squeel/adapters/active_record/3.0/relation'
7
+ require 'squeel/adapters/active_record/3.0/join_dependency'
8
+ require 'squeel/adapters/active_record/3.0/join_association'
9
+ require 'squeel/adapters/active_record/3.0/association_preload'
10
+ require 'squeel/adapters/active_record/3.0/context'
9
11
 
10
- ActiveRecord::Relation.send :include, Squeel::Adapters::ActiveRecord::Relation
11
- ActiveRecord::Associations::ClassMethods::JoinDependency.send :include, Squeel::Adapters::ActiveRecord::JoinDependency
12
- ActiveRecord::Base.extend Squeel::Adapters::ActiveRecord::AssociationPreload
13
- else
14
- require 'squeel/adapters/active_record/relation'
15
- require 'squeel/adapters/active_record/join_dependency'
16
- require 'squeel/adapters/active_record/join_association'
17
- require 'squeel/adapters/active_record/preloader'
18
- require 'squeel/adapters/active_record/context'
12
+ ActiveRecord::Relation.send :include, Squeel::Adapters::ActiveRecord::Relation
13
+ ActiveRecord::Associations::ClassMethods::JoinDependency.send :include, Squeel::Adapters::ActiveRecord::JoinDependency
14
+ ActiveRecord::Base.extend Squeel::Adapters::ActiveRecord::AssociationPreload
15
+ else
16
+ require 'squeel/adapters/active_record/relation'
17
+ require 'squeel/adapters/active_record/join_dependency'
18
+ require 'squeel/adapters/active_record/join_association'
19
+ require 'squeel/adapters/active_record/preloader'
20
+ require 'squeel/adapters/active_record/context'
19
21
 
20
- ActiveRecord::Relation.send :include, Squeel::Adapters::ActiveRecord::Relation
21
- ActiveRecord::Associations::JoinDependency.send :include, Squeel::Adapters::ActiveRecord::JoinDependency
22
- ActiveRecord::Associations::Preloader.send :include, Squeel::Adapters::ActiveRecord::Preloader
22
+ ActiveRecord::Relation.send :include, Squeel::Adapters::ActiveRecord::Relation
23
+ ActiveRecord::Associations::JoinDependency.send :include, Squeel::Adapters::ActiveRecord::JoinDependency
24
+ ActiveRecord::Associations::Preloader.send :include, Squeel::Adapters::ActiveRecord::Preloader
25
+ end
26
+ else
27
+ raise NotImplementedError, "Squeel does not support ActiveRecord version #{ActiveRecord::VERSION::STRING}"
23
28
  end