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
@@ -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