squeel 1.0.18 → 1.1.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 (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
@@ -1,7 +1,7 @@
1
1
  module Squeel
2
2
  module Nodes
3
3
  # Literal nodes are a container for raw SQL.
4
- class Literal
4
+ class Literal < Node
5
5
  include PredicateMethods
6
6
  include PredicateOperators
7
7
  include Operators
@@ -1,7 +1,7 @@
1
1
  module Squeel
2
2
  module Nodes
3
3
  # A node containing multiple children. Just the And node for now.
4
- class Nary
4
+ class Nary < Node
5
5
  include PredicateOperators
6
6
 
7
7
  # @return [Array] This node's children
@@ -17,20 +17,18 @@ module Squeel
17
17
  @children = children
18
18
  end
19
19
 
20
- # Add a new child to the node's children
20
+ # Returns a new Nary node, with an additional child.
21
21
  # @param other A new child node
22
22
  # @return [Nary] This node, with its updated children.
23
23
  def &(other)
24
- @children << other
25
- self
24
+ self.class.new(@children + [other])
26
25
  end
27
26
 
28
- # Append a new Not node to this node's children
27
+ # Returns a new Nary node, with an additional (negated) child.
29
28
  # @param other A new child node
30
29
  # @return [Nary] This node, with its new, negated child
31
30
  def -(other)
32
- @children << Not.new(other)
33
- self
31
+ self.class.new(@children + [Not.new(other)])
34
32
  end
35
33
 
36
34
  # Implemented for equality testing
@@ -0,0 +1,6 @@
1
+ module Squeel
2
+ module Nodes
3
+ class Node
4
+ end
5
+ end
6
+ end
@@ -15,7 +15,7 @@ module Squeel
15
15
  end
16
16
 
17
17
  # An operation should probably call its "function" name an "operator", shouldn't it?
18
- alias :operator :name
18
+ alias :operator :function_name
19
19
 
20
20
  # @return The left operand
21
21
  def left
@@ -1,7 +1,7 @@
1
1
  module Squeel
2
2
  module Nodes
3
3
  # A node that represents SQL orderings, such as "people.id DESC"
4
- class Order
4
+ class Order < Node
5
5
  # @return The expression being ordered on. Might be an attribute, function, or operation
6
6
  attr_reader :expr
7
7
 
@@ -1,11 +1,11 @@
1
1
  module Squeel
2
2
  module Nodes
3
- # This node is essentially a container that will result in ARel predicate nodes
3
+ # This node is essentially a container that will result in Arel predicate nodes
4
4
  # once visited. It stores the expression (normally an attribute name, function, or
5
- # operation), the ARel predicate method name, and a value. these are then interpreted
5
+ # operation), the Arel predicate method name, and a value. these are then interpreted
6
6
  # when visited by the PredicateVisitor to generate a condition against the appropriate
7
7
  # columns.
8
- class Predicate
8
+ class Predicate < Node
9
9
 
10
10
  include PredicateOperators
11
11
  include Aliasing
@@ -16,12 +16,12 @@ module Squeel
16
16
  # @return The expression on the left side of this predicate.
17
17
  attr_reader :expr
18
18
 
19
- # @return [Symbol] The ARel "predication" method name, such as eq, matches, etc.
19
+ # @return [Symbol] The Arel "predication" method name, such as eq, matches, etc.
20
20
  attr_reader :method_name
21
21
 
22
22
  # Create a new Predicate node with the given expression, method name, and value
23
23
  # @param expr The expression for the left hand side of the predicate.
24
- # @param [Symbol] method_name The ARel predication method
24
+ # @param [Symbol] method_name The Arel predication method
25
25
  # @param value An optional value. If not given, one will need to be supplied
26
26
  # before the node can be visited properly.
27
27
  def initialize(expr, method_name = :eq, value = :__undefined__)
@@ -1,9 +1,9 @@
1
1
  module Squeel
2
2
  module Nodes
3
- # Defines Predicate factories named for each of the ARel predication methods
3
+ # Defines Predicate factories named for each of the Arel predication methods
4
4
  module PredicateMethods
5
5
 
6
- Constants::PREDICATES.each do |method_name|
6
+ (Constants::PREDICATES - [:eq]).each do |method_name|
7
7
  class_eval <<-RUBY
8
8
  def #{method_name}(value = :__undefined__)
9
9
  Nodes::Predicate.new self, :#{method_name}, value
@@ -11,6 +11,15 @@ module Squeel
11
11
  RUBY
12
12
  end
13
13
 
14
+ # YAY WHERECHAIN
15
+ def eq(value = :__undefined__)
16
+ if :chain == value
17
+ false
18
+ else
19
+ Nodes::Predicate.new self, :eq, value
20
+ end
21
+ end
22
+
14
23
  end
15
24
  end
16
25
  end
@@ -1,6 +1,6 @@
1
1
  module Squeel
2
2
  module Nodes
3
- class Sifter
3
+ class Sifter < Node
4
4
  include PredicateOperators
5
5
 
6
6
  attr_reader :name, :args
@@ -24,4 +24,4 @@ module Squeel
24
24
 
25
25
  end
26
26
  end
27
- end
27
+ end
@@ -3,7 +3,7 @@ module Squeel
3
3
  # Stub nodes are basically a container for a Symbol that can have handy predicate
4
4
  # methods and operators defined on it since doing so on Symbol will incur the
5
5
  # nerdrage of many.
6
- class Stub
6
+ class Stub < Node
7
7
  include PredicateMethods
8
8
  include Operators
9
9
  include Aliasing
@@ -21,7 +21,7 @@ module Squeel
21
21
  alias :< :lt
22
22
  alias :<= :lteq
23
23
 
24
- # We dn't want these default Object methods, because if we're
24
+ # We don't want these default Object methods, because if we're
25
25
  # calling them we are probably talking about a column name
26
26
  [:id, :type].each do |column_method|
27
27
  undef_method column_method if method_defined?(column_method) ||
@@ -1,7 +1,7 @@
1
1
  module Squeel
2
2
  module Nodes
3
3
  # A node that contains a single expression.
4
- class Unary
4
+ class Unary < Node
5
5
 
6
6
  include PredicateOperators
7
7
 
@@ -1,3 +1,3 @@
1
1
  module Squeel
2
- VERSION = "1.0.18"
2
+ VERSION = '1.1.0'
3
3
  end
@@ -16,14 +16,14 @@ module Squeel
16
16
  # @return The result of visiting the executed block's return value
17
17
  def visit_Squeel_Nodes_Sifter(o, parent)
18
18
  klass = classify(parent)
19
- visit(klass.send(o.name, *o.args), parent)
19
+ visit(klass.send("sifter_#{o.name}", *o.args), parent)
20
20
  end
21
21
 
22
- # Visit a Squeel predicate, converting it into an ARel predicate
22
+ # Visit a Squeel predicate, converting it into an Arel predicate
23
23
  #
24
24
  # @param [Nodes::Predicate] o The predicate to visit
25
25
  # @param parent The parent object in the context
26
- # @return An ARel predicate node
26
+ # @return An Arel predicate node
27
27
  # (Arel::Nodes::Equality, Arel::Nodes::Matches, etc)
28
28
  def visit_Squeel_Nodes_Predicate(o, parent)
29
29
  value = o.value
@@ -59,10 +59,10 @@ module Squeel
59
59
  # Determine whether to use IN or equality testing for a predicate,
60
60
  # based on its value class, then return the appropriate predicate.
61
61
  #
62
- # @param attribute The ARel attribute (or function/operation) the
62
+ # @param attribute The Arel attribute (or function/operation) the
63
63
  # predicate will be created for
64
64
  # @param value The value to be compared against
65
- # @return [Arel::Nodes::Node] An ARel predicate node
65
+ # @return [Arel::Nodes::Node] An Arel predicate node
66
66
  def arel_predicate_for(attribute, value, parent)
67
67
  if ActiveRecord::Relation === value && value.select_values.empty?
68
68
  value = visit(value.select(value.klass.arel_table[value.klass.primary_key]), parent)
@@ -102,7 +102,7 @@ module Squeel
102
102
  end
103
103
  end
104
104
 
105
- # Certain nodes require us to do the quoting before the ARel
105
+ # Certain nodes require us to do the quoting before the Arel
106
106
  # visitor gets a chance to try, because we want to avoid having our
107
107
  # values quoted as a type of the last visited column. Otherwise, we
108
108
  # can end up with annoyances like having "joe" quoted to 0, if the
@@ -45,7 +45,7 @@ module Squeel
45
45
  # @param k The hash key
46
46
  # @param v The hash value
47
47
  # @param parent The current parent object in the context
48
- # @return An ARel predicate
48
+ # @return An Arel predicate
49
49
  def visit_without_hash_context_shift(k, v, parent)
50
50
  case v
51
51
  when Nodes::Stub, Symbol
@@ -22,7 +22,7 @@ module Squeel
22
22
  # @param object The object to visit
23
23
  # @param parent The parent of this object, to track the object's place in
24
24
  # any association hierarchy.
25
- # @return The results of the node visitation, typically an ARel object of some kind.
25
+ # @return The results of the node visitation, typically an Arel object of some kind.
26
26
  def accept(object, parent = context.base)
27
27
  visit(object, parent)
28
28
  end
@@ -100,13 +100,13 @@ module Squeel
100
100
  v
101
101
  end
102
102
 
103
- # Important to avoid accidentally allowing the default ARel visitor's
103
+ # Important to avoid accidentally allowing the default Arel visitor's
104
104
  # last_column quoting behavior (where a value is quoted as though it
105
105
  # is of the type of the last visited column). This can wreak havoc with
106
106
  # Functions and Operations.
107
107
  #
108
108
  # @param object The object to check
109
- # @return [Boolean] Whether or not the ARel visitor will try to quote the
109
+ # @return [Boolean] Whether or not the Arel visitor will try to quote the
110
110
  # object if not passed as an SqlLiteral.
111
111
  def quoted?(object)
112
112
  case object
@@ -119,7 +119,7 @@ module Squeel
119
119
  end
120
120
 
121
121
  # Quote a value based on its type, not on the last column used by the
122
- # ARel visitor. This is occasionally necessary to avoid having ARel
122
+ # Arel visitor. This is occasionally necessary to avoid having Arel
123
123
  # quote a value according to an integer column, converting 'My String' to 0.
124
124
  #
125
125
  # @param value The value to quote
@@ -159,7 +159,7 @@ module Squeel
159
159
 
160
160
  # Pass an object through the visitor unmodified. This is
161
161
  # in order to allow objects that don't require modification
162
- # to be handled by ARel directly.
162
+ # to be handled by Arel directly.
163
163
  #
164
164
  # @param object The object to visit
165
165
  # @param parent The object's parent within the context
@@ -231,7 +231,7 @@ module Squeel
231
231
  visit(o.endpoint, parent)
232
232
  end
233
233
 
234
- # Visit a Literal by converting it to an ARel SqlLiteral
234
+ # Visit a Literal by converting it to an Arel SqlLiteral
235
235
  #
236
236
  # @param [Nodes::Literal] o The Literal to visit
237
237
  # @param parent The parent object in the context (unused)
@@ -240,7 +240,7 @@ module Squeel
240
240
  Arel.sql(o.expr)
241
241
  end
242
242
 
243
- # Visit a Squeel As node, resulting in am ARel As node.
243
+ # Visit a Squeel As node, resulting in am Arel As node.
244
244
  #
245
245
  # @param [Nodes::As] The As node to visit
246
246
  # @param parent The parent object in the context
@@ -256,46 +256,46 @@ module Squeel
256
256
  end
257
257
  end
258
258
 
259
- # Visit a Squeel And node, returning an ARel Grouping containing an
260
- # ARel And node.
259
+ # Visit a Squeel And node, returning an Arel Grouping containing an
260
+ # Arel And node.
261
261
  #
262
262
  # @param [Nodes::And] o The And node to visit
263
263
  # @param parent The parent object in the context
264
- # @return [Arel::Nodes::Grouping] A grouping node, containnig an ARel
264
+ # @return [Arel::Nodes::Grouping] A grouping node, containnig an Arel
265
265
  # And node as its expression. All children will be visited before
266
266
  # being passed to the And.
267
267
  def visit_Squeel_Nodes_And(o, parent)
268
268
  Arel::Nodes::Grouping.new(Arel::Nodes::And.new(visit(o.children, parent)))
269
269
  end
270
270
 
271
- # Visit a Squeel Or node, returning an ARel Or node.
271
+ # Visit a Squeel Or node, returning an Arel Or node.
272
272
  #
273
273
  # @param [Nodes::Or] o The Or node to visit
274
274
  # @param parent The parent object in the context
275
- # @return [Arel::Nodes::Or] An ARel Or node, with left and right sides visited
275
+ # @return [Arel::Nodes::Or] An Arel Or node, with left and right sides visited
276
276
  def visit_Squeel_Nodes_Or(o, parent)
277
277
  Arel::Nodes::Grouping.new(Arel::Nodes::Or.new(visit(o.left, parent), (visit(o.right, parent))))
278
278
  end
279
279
 
280
- # Visit a Squeel Not node, returning an ARel Not node.
280
+ # Visit a Squeel Not node, returning an Arel Not node.
281
281
  #
282
282
  # @param [Nodes::Not] o The Not node to visit
283
283
  # @param parent The parent object in the context
284
- # @return [Arel::Nodes::Not] An ARel Not node, with expression visited
284
+ # @return [Arel::Nodes::Not] An Arel Not node, with expression visited
285
285
  def visit_Squeel_Nodes_Not(o, parent)
286
286
  Arel::Nodes::Not.new(visit(o.expr, parent))
287
287
  end
288
288
 
289
- # Visit a Squeel Grouping node, returning an ARel Grouping node.
289
+ # Visit a Squeel Grouping node, returning an Arel Grouping node.
290
290
  #
291
291
  # @param [Nodes::Grouping] o The Grouping node to visit
292
292
  # @param parent The parent object in the context
293
- # @return [Arel::Nodes::Grouping] An ARel Grouping node, with expression visited
293
+ # @return [Arel::Nodes::Grouping] An Arel Grouping node, with expression visited
294
294
  def visit_Squeel_Nodes_Grouping(o, parent)
295
295
  Arel::Nodes::Grouping.new(visit(o.expr, parent))
296
296
  end
297
297
  #
298
- # Visit a Squeel function, returning an ARel NamedFunction node.
298
+ # Visit a Squeel function, returning an Arel NamedFunction node.
299
299
  #
300
300
  # @param [Nodes::Function] o The function node to visit
301
301
  # @param parent The parent object in the context
@@ -315,10 +315,10 @@ module Squeel
315
315
  end
316
316
  end
317
317
 
318
- Arel::Nodes::NamedFunction.new(o.name, args)
318
+ Arel::Nodes::NamedFunction.new(o.function_name, args)
319
319
  end
320
320
 
321
- # Visit a Squeel operation node, convering it to an ARel InfixOperation
321
+ # Visit a Squeel operation node, convering it to an Arel InfixOperation
322
322
  # (or subclass, as appropriate)
323
323
  #
324
324
  # @param [Nodes::Operation] o The Operation node to visit
@@ -356,7 +356,7 @@ module Squeel
356
356
  # Visit an Active Record Relation, returning an Arel::SelectManager
357
357
  # @param [ActiveRecord::Relation] o The Relation to visit
358
358
  # @param parent The parent object in the context
359
- # @return [Arel::SelectManager] The ARel select manager that represents
359
+ # @return [Arel::SelectManager] The Arel select manager that represents
360
360
  # the relation's query
361
361
  def visit_ActiveRecord_Relation(o, parent)
362
362
  o.arel
@@ -3,12 +3,10 @@ require 'sham'
3
3
  require 'faker'
4
4
 
5
5
  module ActiveRecord
6
+ # Shamelessly swiped from the AR test code
6
7
  class SQLCounter
7
8
  IGNORED_SQL = [/^PRAGMA /, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/,
8
9
  /SELECT name\s+FROM sqlite_master\s+WHERE type = 'table' AND NOT name = 'sqlite_sequence'/]
9
-
10
- # FIXME: this needs to be refactored so specific database can add their own
11
- # ignored SQL. This ignored SQL is for Oracle.
12
10
  IGNORED_SQL.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im]
13
11
 
14
12
  def initialize
@@ -26,6 +24,10 @@ module ActiveRecord
26
24
  ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)
27
25
  end
28
26
 
27
+ unless ENV['DEPRECATIONS']
28
+ ActiveSupport::Deprecation.silenced = true
29
+ end
30
+
29
31
  Dir[File.expand_path('../helpers/*.rb', __FILE__)].each do |f|
30
32
  require f
31
33
  end
@@ -45,7 +47,7 @@ end
45
47
  RSpec.configure do |config|
46
48
  config.before(:suite) do
47
49
  puts '=' * 80
48
- puts "Running specs against Active Record #{ActiveRecord::VERSION::STRING} and ARel #{Arel::VERSION}..."
50
+ puts "Running specs against Active Record #{ActiveRecord::VERSION::STRING} and Arel #{Arel::VERSION}..."
49
51
  puts '=' * 80
50
52
  Models.make
51
53
  end
@@ -22,19 +22,19 @@ module Squeel
22
22
  end
23
23
  end
24
24
 
25
- it { should respond_to :title_or_body_contains }
26
- specify { subject.title_or_body_contains('ernie').should be_a Nodes::Or }
25
+ it { should respond_to :sifter_title_or_body_contains }
26
+ specify { subject.sifter_title_or_body_contains('ernie').should be_a Nodes::Or }
27
27
  end
28
28
 
29
29
  context 'with a sifter defined via method' do
30
30
  before :all do
31
- def subject.title_starts_with(val)
31
+ def subject.sifter_title_starts_with(val)
32
32
  squeel{title =~ "#{val}%"}
33
33
  end
34
34
  end
35
35
 
36
- it { should respond_to :title_starts_with }
37
- specify { subject.title_starts_with('ernie').should be_a Nodes::Predicate }
36
+ it { should respond_to :sifter_title_starts_with }
37
+ specify { subject.sifter_title_starts_with('ernie').should be_a Nodes::Predicate }
38
38
  end
39
39
 
40
40
  end
@@ -42,4 +42,4 @@ module Squeel
42
42
  end
43
43
  end
44
44
  end
45
- end
45
+ end
@@ -78,7 +78,7 @@ module Squeel
78
78
  Article.first.uniq_commenters.length.should eq Article.first.uniq_commenters.count
79
79
  end
80
80
 
81
- it 'visits wheres with a PredicateVisitor, converting them to ARel nodes' do
81
+ it 'visits wheres with a PredicateVisitor, converting them to Arel nodes' do
82
82
  relation = Person.where(:name.matches => '%bob%')
83
83
  arel = relation.build_arel
84
84
  arel.to_sql.should match /"people"."name" LIKE '%bob%'/
@@ -155,25 +155,29 @@ module Squeel
155
155
  end
156
156
 
157
157
  it 'maps orders inside a hash to their appropriate association table' do
158
- relation = Person.joins({
159
- :children => {
158
+ unless activerecord_version_at_least '4.0.0'
159
+ relation = Person.joins({
160
160
  :children => {
161
- :parent => :parent
161
+ :children => {
162
+ :parent => :parent
163
+ }
162
164
  }
163
- }
164
- }).order({
165
- :children => {
165
+ }).order({
166
166
  :children => {
167
- :parent => {
168
- :parent => :id.asc
167
+ :children => {
168
+ :parent => {
169
+ :parent => :id.asc
170
+ }
169
171
  }
170
172
  }
171
- }
172
- })
173
+ })
173
174
 
174
- arel = relation.build_arel
175
+ arel = relation.build_arel
175
176
 
176
- arel.to_sql.should match /ORDER BY "parents_people_2"."id" ASC/
177
+ arel.to_sql.should match /ORDER BY "parents_people_2"."id" ASC/
178
+ else
179
+ pending 'Unsupported in ActiveRecord 4.0.0+'
180
+ end
177
181
  end
178
182
 
179
183
  it 'does not inadvertently convert KeyPaths to booleans when uniqing where_values' do
@@ -186,7 +190,7 @@ module Squeel
186
190
  end
187
191
 
188
192
  it 'reverses order of Arel::Attributes when #last is called' do
189
- sorted_people = Person.all.sort {|a, b| a.name.downcase <=> b.name.downcase}
193
+ sorted_people = Person.all.to_a.sort {|a, b| a.name.downcase <=> b.name.downcase}
190
194
 
191
195
  Person.order{name}.last.should eq sorted_people.last
192
196
  end
@@ -242,7 +246,7 @@ module Squeel
242
246
  it 'eager loads belongs_to associations' do
243
247
  queries = queries_for do
244
248
  Article.includes(:person).
245
- where{person.name == 'Ernie'}.all
249
+ where{person.name == 'Ernie'}.to_a
246
250
  end
247
251
  queries.should have(1).item
248
252
  queries.first.should match /LEFT OUTER JOIN "people"/
@@ -252,7 +256,7 @@ module Squeel
252
256
  it 'eager loads belongs_to associations on models with default_scopes' do
253
257
  queries = queries_for do
254
258
  PersonNamedBill.includes(:parent).
255
- where{parent.name == 'Ernie'}.all
259
+ where{parent.name == 'Ernie'}.to_a
256
260
  end
257
261
  queries.should have(1).item
258
262
  queries.first.should match /LEFT OUTER JOIN "people"/
@@ -289,13 +293,13 @@ module Squeel
289
293
 
290
294
  it 'builds options with a block' do
291
295
  relation = Person.preload{children}
292
- queries_for {relation.all}.should have(2).items
296
+ queries_for {relation.to_a}.should have(2).items
293
297
  queries_for {relation.first.children}.should have(0).items
294
298
  end
295
299
 
296
300
  it 'builds options with a keypath' do
297
301
  relation = Person.preload{articles.comments}
298
- queries_for {relation.all}.should have(3).items
302
+ queries_for {relation.to_a}.should have(3).items
299
303
  queries_for {relation.first.articles.first.comments}.should have(0).items
300
304
  end
301
305
 
@@ -306,7 +310,7 @@ module Squeel
306
310
  }
307
311
  }}
308
312
 
309
- queries_for {relation.all}.should have(4).items
313
+ queries_for {relation.to_a}.should have(4).items
310
314
 
311
315
  queries_for {
312
316
  relation.first.articles
@@ -323,7 +327,7 @@ module Squeel
323
327
  standard = Person.eager_load(:children => :children)
324
328
  block = Person.eager_load{{children => children}}
325
329
  block.debug_sql.should eq standard.debug_sql
326
- queries_for {block.all}.should have(1).item
330
+ queries_for {block.to_a}.should have(1).item
327
331
  queries_for {block.first.children}.should have(0).items
328
332
  end
329
333
 
@@ -417,7 +421,11 @@ module Squeel
417
421
  describe '#count' do
418
422
 
419
423
  it 'works with non-strings in select' do
420
- Article.select{distinct(title)}.count.should eq 51
424
+ if activerecord_version_at_least '4.0.0'
425
+ pending 'broken on current 4-0-stable'
426
+ else
427
+ Article.select{distinct(title)}.count.should eq 51
428
+ end
421
429
  end
422
430
 
423
431
  it 'works with non-strings in wheres' do
@@ -496,6 +504,16 @@ module Squeel
496
504
  old_and_busted.to_a.should eq new_hotness.to_a
497
505
  end
498
506
 
507
+ it 'is backwards-compatible with "where.not"' do
508
+ if activerecord_version_at_least '4.0.0'
509
+ name = Person.first.name
510
+ result = Person.where.not(:name => name)
511
+ result.should_not include Person.first
512
+ else
513
+ pending 'Not required pre-4.0'
514
+ end
515
+ end
516
+
499
517
  end
500
518
 
501
519
  describe '#joins' do
@@ -572,9 +590,22 @@ module Squeel
572
590
  describe '#order' do
573
591
 
574
592
  it 'builds options with a block' do
575
- standard = Person.order(:name)
576
593
  block = Person.order{name}
577
- block.to_sql.should eq standard.to_sql
594
+ block.to_sql.should match /ORDER BY "people"\."name"/
595
+ end
596
+
597
+ it 'allows AR 4.0-style hash options' do
598
+ if activerecord_version_at_least '4.0.0'
599
+ block = Person.order(:name => :desc)
600
+ block.to_sql.should match /ORDER BY "people"\."name" DESC/
601
+ else
602
+ pending 'Not required in AR versions < 4.0.0'
603
+ end
604
+ end
605
+
606
+ it 'allows ordering by an attributes of a joined table' do
607
+ relation = Article.joins(:person).order { person.id.asc }
608
+ relation.to_sql.should match /ORDER BY "people"\."id" ASC/
578
609
  end
579
610
 
580
611
  end
@@ -631,7 +662,7 @@ module Squeel
631
662
  wheres.should eq ["name like '%bob%'"]
632
663
  end
633
664
 
634
- it 'adds hash where values without converting to ARel predicates' do
665
+ it 'adds hash where values without converting to Arel predicates' do
635
666
  wheres = Person.where({:name => 'bob'}).where_values
636
667
  wheres.should eq [{:name => 'bob'}]
637
668
  end