Skip to content
This repository
Browse code

Add equality to ALL THE THINGS (that matter)

People are often trying to use ARel nodes inside ActiveRecord, and when
they do so, lots of things can break, because ActiveRecord relies on
Array#uniq and sometimes hash key equality to handle values that end up
in wheres, havings, etc. By implementing equality for all the nodes, we
should hopefully be able to prevent any nodes (even nodes containing
other nodes) from failing an equality check they should otherwise pass,
and alleviate many of these errors.

Fixes #130
  • Loading branch information...
commit 6e638bba594b6164190d2a6fb96ffa07a20b11f3 1 parent 1de1041
Ernie Miller authored August 18, 2012

Showing 43 changed files with 737 additions and 4 deletions. Show diff stats Hide diff stats

  1. 10  lib/arel/nodes/and.rb
  2. 11  lib/arel/nodes/binary.rb
  3. 11  lib/arel/nodes/extract.rb
  4. 7  lib/arel/nodes/false.rb
  5. 11  lib/arel/nodes/function.rb
  6. 12  lib/arel/nodes/insert_statement.rb
  7. 9  lib/arel/nodes/named_function.rb
  8. 20  lib/arel/nodes/select_core.rb
  9. 16  lib/arel/nodes/select_statement.rb
  10. 7  lib/arel/nodes/terminal.rb
  11. 7  lib/arel/nodes/true.rb
  12. 10  lib/arel/nodes/unary.rb
  13. 15  lib/arel/nodes/update_statement.rb
  14. 30  lib/arel/nodes/window.rb
  15. 13  lib/arel/table.rb
  16. 20  test/nodes/test_and.rb
  17. 12  test/nodes/test_as.rb
  18. 10  test/nodes/test_ascending.rb
  19. 10  test/nodes/test_bin.rb
  20. 12  test/nodes/test_count.rb
  21. 20  test/nodes/test_delete_statement.rb
  22. 10  test/nodes/test_descending.rb
  23. 20  test/nodes/test_distinct.rb
  24. 10  test/nodes/test_equality.rb
  25. 14  test/nodes/test_extract.rb
  26. 20  test/nodes/test_false.rb
  27. 12  test/nodes/test_grouping.rb
  28. 10  test/nodes/test_infix_operation.rb
  29. 24  test/nodes/test_insert_statement.rb
  30. 16  test/nodes/test_named_function.rb
  31. 12  test/nodes/test_not.rb
  32. 12  test/nodes/test_or.rb
  33. 18  test/nodes/test_over.rb
  34. 38  test/nodes/test_select_core.rb
  35. 36  test/nodes/test_select_statement.rb
  36. 10  test/nodes/test_sql_literal.rb
  37. 12  test/nodes/test_sum.rb
  38. 24  test/nodes/test_table_alias.rb
  39. 21  test/nodes/test_true.rb
  40. 40  test/nodes/test_update_statement.rb
  41. 73  test/nodes/test_window.rb
  42. 12  test/test_attributes.rb
  43. 24  test/test_table.rb
10  lib/arel/nodes/and.rb
@@ -18,6 +18,16 @@ def left
18 18
       def right
19 19
         children[1]
20 20
       end
  21
+
  22
+      def hash
  23
+        children.hash
  24
+      end
  25
+
  26
+      def eql? other
  27
+        self.class == other.class &&
  28
+          self.children == other.children
  29
+      end
  30
+      alias :== :eql?
21 31
     end
22 32
   end
23 33
 end
11  lib/arel/nodes/binary.rb
@@ -13,6 +13,17 @@ def initialize_copy other
13 13
         @left  = @left.clone if @left
14 14
         @right = @right.clone if @right
15 15
       end
  16
+
  17
+      def hash
  18
+        [@left, @right].hash
  19
+      end
  20
+
  21
+      def eql? other
  22
+        self.class == other.class &&
  23
+          self.left == other.left &&
  24
+          self.right == other.right
  25
+      end
  26
+      alias :== :eql?
16 27
     end
17 28
 
18 29
     %w{
11  lib/arel/nodes/extract.rb
@@ -18,6 +18,17 @@ def as aliaz
18 18
         self.alias = SqlLiteral.new(aliaz)
19 19
         self
20 20
       end
  21
+
  22
+      def hash
  23
+        super ^ [@field, @alias].hash
  24
+      end
  25
+
  26
+      def eql? other
  27
+        super &&
  28
+          self.field == other.field &&
  29
+          self.alias == other.alias
  30
+      end
  31
+      alias :== :eql?
21 32
     end
22 33
   end
23 34
 end
7  lib/arel/nodes/false.rb
... ...
@@ -1,6 +1,13 @@
1 1
 module Arel
2 2
   module Nodes
3 3
     class False < Arel::Nodes::Node
  4
+      def hash
  5
+        self.class.hash
  6
+      end
  7
+
  8
+      def eql? other
  9
+        self.class == other.class
  10
+      end
4 11
     end
5 12
   end
6 13
 end
11  lib/arel/nodes/function.rb
@@ -16,6 +16,17 @@ def as aliaz
16 16
         self.alias = SqlLiteral.new(aliaz)
17 17
         self
18 18
       end
  19
+
  20
+      def hash
  21
+        [@expressions, @alias, @distinct].hash
  22
+      end
  23
+
  24
+      def eql? other
  25
+        self.class == other.class &&
  26
+          self.expressions == other.expressions &&
  27
+          self.alias == other.alias &&
  28
+          self.distinct == other.distinct
  29
+      end
19 30
     end
20 31
 
21 32
     %w{
12  lib/arel/nodes/insert_statement.rb
@@ -14,6 +14,18 @@ def initialize_copy other
14 14
         @columns = @columns.clone
15 15
         @values =  @values.clone if @values
16 16
       end
  17
+
  18
+      def hash
  19
+        [@relation, @columns, @values].hash
  20
+      end
  21
+
  22
+      def eql? other
  23
+        self.class == other.class &&
  24
+          self.relation == other.relation &&
  25
+          self.columns == other.columns &&
  26
+          self.values == other.values
  27
+      end
  28
+      alias :== :eql?
17 29
     end
18 30
   end
19 31
 end
9  lib/arel/nodes/named_function.rb
@@ -7,6 +7,15 @@ def initialize name, expr, aliaz = nil
7 7
         super(expr, aliaz)
8 8
         @name = name
9 9
       end
  10
+
  11
+      def hash
  12
+        super ^ @name.hash
  13
+      end
  14
+
  15
+      def eql? other
  16
+        super && self.name == other.name
  17
+      end
  18
+      alias :== :eql?
10 19
     end
11 20
   end
12 21
 end
20  lib/arel/nodes/select_core.rb
@@ -37,6 +37,26 @@ def initialize_copy other
37 37
         @having      = @having.clone if @having
38 38
         @windows     = @windows.clone
39 39
       end
  40
+
  41
+      def hash
  42
+        [
  43
+          @source, @top, @set_quantifier, @projections,
  44
+          @wheres, @groups, @having, @windows
  45
+        ].hash
  46
+      end
  47
+
  48
+      def eql? other
  49
+        self.class == other.class &&
  50
+          self.source == other.source &&
  51
+          self.top == other.top &&
  52
+          self.set_quantifier == other.set_quantifier &&
  53
+          self.projections == other.projections &&
  54
+          self.wheres == other.wheres &&
  55
+          self.groups == other.groups &&
  56
+          self.having == other.having &&
  57
+          self.windows == other.windows
  58
+      end
  59
+      alias :== :eql?
40 60
     end
41 61
   end
42 62
 end
16  lib/arel/nodes/select_statement.rb
@@ -5,7 +5,6 @@ class SelectStatement < Arel::Nodes::Node
5 5
       attr_accessor :limit, :orders, :lock, :offset, :with
6 6
 
7 7
       def initialize cores = [SelectCore.new]
8  
-        #puts caller
9 8
         @cores          = cores
10 9
         @orders         = []
11 10
         @limit          = nil
@@ -19,6 +18,21 @@ def initialize_copy other
19 18
         @cores  = @cores.map { |x| x.clone }
20 19
         @orders = @orders.map { |x| x.clone }
21 20
       end
  21
+
  22
+      def hash
  23
+        [@cores, @orders, @limit, @lock, @offset, @with].hash
  24
+      end
  25
+
  26
+      def eql? other
  27
+        self.class == other.class &&
  28
+          self.cores == other.cores &&
  29
+          self.orders == other.orders &&
  30
+          self.limit == other.limit &&
  31
+          self.lock == other.lock &&
  32
+          self.offset == other.offset &&
  33
+          self.with == other.with
  34
+      end
  35
+      alias :== :eql?
22 36
     end
23 37
   end
24 38
 end
7  lib/arel/nodes/terminal.rb
... ...
@@ -1,6 +1,13 @@
1 1
 module Arel
2 2
   module Nodes
3 3
     class Distinct < Arel::Nodes::Node
  4
+      def hash
  5
+        self.class.hash
  6
+      end
  7
+
  8
+      def eql? other
  9
+        self.class == other.class
  10
+      end
4 11
     end
5 12
   end
6 13
 end
7  lib/arel/nodes/true.rb
... ...
@@ -1,6 +1,13 @@
1 1
 module Arel
2 2
   module Nodes
3 3
     class True < Arel::Nodes::Node
  4
+      def hash
  5
+        self.class.hash
  6
+      end
  7
+
  8
+      def eql? other
  9
+        self.class == other.class
  10
+      end
4 11
     end
5 12
   end
6 13
 end
10  lib/arel/nodes/unary.rb
@@ -7,6 +7,16 @@ class Unary < Arel::Nodes::Node
7 7
       def initialize expr
8 8
         @expr = expr
9 9
       end
  10
+
  11
+      def hash
  12
+        @expr.hash
  13
+      end
  14
+
  15
+      def eql? other
  16
+        self.class == other.class &&
  17
+          self.expr == other.expr
  18
+      end
  19
+      alias :== :eql?
10 20
     end
11 21
 
12 22
     %w{
15  lib/arel/nodes/update_statement.rb
@@ -18,6 +18,21 @@ def initialize_copy other
18 18
         @wheres = @wheres.clone
19 19
         @values = @values.clone
20 20
       end
  21
+
  22
+      def hash
  23
+        [@relation, @wheres, @values, @orders, @limit, @key].hash
  24
+      end
  25
+
  26
+      def eql? other
  27
+        self.class == other.class &&
  28
+          self.relation == other.relation &&
  29
+          self.wheres == other.wheres &&
  30
+          self.values == other.values &&
  31
+          self.orders == other.orders &&
  32
+          self.limit == other.limit &&
  33
+          self.key == other.key
  34
+      end
  35
+      alias :== :eql?
21 36
     end
22 37
   end
23 38
 end
30  lib/arel/nodes/window.rb
@@ -32,6 +32,17 @@ def initialize_copy other
32 32
         super
33 33
         @orders = @orders.map { |x| x.clone }
34 34
       end
  35
+
  36
+      def hash
  37
+        [@orders, @framing].hash
  38
+      end
  39
+
  40
+      def eql? other
  41
+        self.class == other.class &&
  42
+          self.orders == other.orders &&
  43
+          self.framing == other.framing
  44
+      end
  45
+      alias :== :eql?
35 46
     end
36 47
 
37 48
     class NamedWindow < Window
@@ -46,6 +57,15 @@ def initialize_copy other
46 57
         super
47 58
         @name = other.name.clone
48 59
       end
  60
+
  61
+      def hash
  62
+        super ^ @name.hash
  63
+      end
  64
+
  65
+      def eql? other
  66
+        super && self.name == other.name
  67
+      end
  68
+      alias :== :eql?
49 69
     end
50 70
 
51 71
     class Rows < Unary
@@ -60,7 +80,15 @@ def initialize(expr = nil)
60 80
       end
61 81
     end
62 82
 
63  
-    class CurrentRow < Arel::Nodes::Node; end
  83
+    class CurrentRow < Node
  84
+      def hash
  85
+        self.class.hash
  86
+      end
  87
+
  88
+      def eql? other
  89
+        self.class == other.class
  90
+      end
  91
+    end
64 92
 
65 93
     class Preceding < Unary
66 94
       def initialize(expr = nil)
13  lib/arel/table.rb
@@ -123,6 +123,19 @@ def insert_manager
123 123
       InsertManager.new(@engine)
124 124
     end
125 125
 
  126
+    def hash
  127
+      [@name, @engine, @aliases, @table_alias].hash
  128
+    end
  129
+
  130
+    def eql? other
  131
+      self.class == other.class &&
  132
+        self.name == other.name &&
  133
+        self.engine == other.engine &&
  134
+        self.aliases == other.aliases &&
  135
+        self.table_alias == other.table_alias
  136
+    end
  137
+    alias :== :eql?
  138
+
126 139
     private
127 140
 
128 141
     def attributes_for columns
20  test/nodes/test_and.rb
... ...
@@ -0,0 +1,20 @@
  1
+require 'helper'
  2
+
  3
+module Arel
  4
+  module Nodes
  5
+    describe 'And' do
  6
+      describe 'equality' do
  7
+        it 'is equal with equal ivars' do
  8
+          array = [And.new(['foo', 'bar']), And.new(['foo', 'bar'])]
  9
+          assert_equal 1, array.uniq.size
  10
+        end
  11
+
  12
+        it 'is not equal with different ivars' do
  13
+          array = [And.new(['foo', 'bar']), And.new(['foo', 'baz'])]
  14
+          assert_equal 2, array.uniq.size
  15
+        end
  16
+      end
  17
+    end
  18
+  end
  19
+end
  20
+
12  test/nodes/test_as.rb
@@ -17,6 +17,18 @@ module Nodes
17 17
           assert_kind_of Arel::Nodes::SqlLiteral, as.right
18 18
         end
19 19
       end
  20
+
  21
+      describe 'equality' do
  22
+        it 'is equal with equal ivars' do
  23
+          array = [As.new('foo', 'bar'), As.new('foo', 'bar')]
  24
+          assert_equal 1, array.uniq.size
  25
+        end
  26
+
  27
+        it 'is not equal with different ivars' do
  28
+          array = [As.new('foo', 'bar'), As.new('foo', 'baz')]
  29
+          assert_equal 2, array.uniq.size
  30
+        end
  31
+      end
20 32
     end
21 33
   end
22 34
 end
10  test/nodes/test_ascending.rb
@@ -29,6 +29,16 @@ def test_descending?
29 29
         ascending = Ascending.new 'zomg'
30 30
         assert !ascending.descending?
31 31
       end
  32
+
  33
+      def test_equality_with_same_ivars
  34
+        array = [Ascending.new('zomg'), Ascending.new('zomg')]
  35
+        assert_equal 1, array.uniq.size
  36
+      end
  37
+
  38
+      def test_inequality_with_different_ivars
  39
+        array = [Ascending.new('zomg'), Ascending.new('zomg!')]
  40
+        assert_equal 2, array.uniq.size
  41
+      end
32 42
     end
33 43
   end
34 44
 end
10  test/nodes/test_bin.rb
@@ -18,6 +18,16 @@ def test_mysql_to_sql
18 18
         node = Arel::Nodes::Bin.new(Arel.sql('zomg'))
19 19
         assert_equal 'BINARY zomg', viz.accept(node)
20 20
       end
  21
+
  22
+      def test_equality_with_same_ivars
  23
+        array = [Bin.new('zomg'), Bin.new('zomg')]
  24
+        assert_equal 1, array.uniq.size
  25
+      end
  26
+
  27
+      def test_inequality_with_different_ivars
  28
+        array = [Bin.new('zomg'), Bin.new('zomg!')]
  29
+        assert_equal 2, array.uniq.size
  30
+      end
21 31
     end
22 32
   end
23 33
 end
12  test/nodes/test_count.rb
@@ -24,4 +24,16 @@
24 24
       }
25 25
     end
26 26
   end
  27
+
  28
+  describe 'equality' do
  29
+    it 'is equal with equal ivars' do
  30
+      array = [Arel::Nodes::Count.new('foo'), Arel::Nodes::Count.new('foo')]
  31
+      assert_equal 1, array.uniq.size
  32
+    end
  33
+
  34
+    it 'is not equal with different ivars' do
  35
+      array = [Arel::Nodes::Count.new('foo'), Arel::Nodes::Count.new('foo!')]
  36
+      assert_equal 2, array.uniq.size
  37
+    end
  38
+  end
27 39
 end
20  test/nodes/test_delete_statement.rb
@@ -11,4 +11,24 @@
11 11
       dolly.wheres.wont_be_same_as statement.wheres
12 12
     end
13 13
   end
  14
+
  15
+  describe 'equality' do
  16
+    it 'is equal with equal ivars' do
  17
+      statement1 = Arel::Nodes::DeleteStatement.new
  18
+      statement1.wheres = %w[a b c]
  19
+      statement2 = Arel::Nodes::DeleteStatement.new
  20
+      statement2.wheres = %w[a b c]
  21
+      array = [statement1, statement2]
  22
+      assert_equal 1, array.uniq.size
  23
+    end
  24
+
  25
+    it 'is not equal with different ivars' do
  26
+      statement1 = Arel::Nodes::DeleteStatement.new
  27
+      statement1.wheres = %w[a b c]
  28
+      statement2 = Arel::Nodes::DeleteStatement.new
  29
+      statement2.wheres = %w[1 2 3]
  30
+      array = [statement1, statement2]
  31
+      assert_equal 2, array.uniq.size
  32
+    end
  33
+  end
14 34
 end
10  test/nodes/test_descending.rb
@@ -29,6 +29,16 @@ def test_descending?
29 29
         descending = Descending.new 'zomg'
30 30
         assert descending.descending?
31 31
       end
  32
+
  33
+      def test_equality_with_same_ivars
  34
+        array = [Descending.new('zomg'), Descending.new('zomg')]
  35
+        assert_equal 1, array.uniq.size
  36
+      end
  37
+
  38
+      def test_inequality_with_different_ivars
  39
+        array = [Descending.new('zomg'), Descending.new('zomg!')]
  40
+        assert_equal 2, array.uniq.size
  41
+      end
32 42
     end
33 43
   end
34 44
 end
20  test/nodes/test_distinct.rb
... ...
@@ -0,0 +1,20 @@
  1
+require 'helper'
  2
+
  3
+module Arel
  4
+  module Nodes
  5
+    describe 'Distinct' do
  6
+      describe 'equality' do
  7
+        it 'is equal to other distinct nodes' do
  8
+          array = [Distinct.new, Distinct.new]
  9
+          assert_equal 1, array.uniq.size
  10
+        end
  11
+
  12
+        it 'is not equal with other nodes' do
  13
+          array = [Distinct.new, Node.new]
  14
+          assert_equal 2, array.uniq.size
  15
+        end
  16
+      end
  17
+    end
  18
+  end
  19
+end
  20
+
10  test/nodes/test_equality.rb
@@ -69,6 +69,16 @@ def quote_table_name(*args) @quote_count += 1; super; end
69 69
           node.right.must_equal right
70 70
         end
71 71
       end
  72
+
  73
+      it 'is equal with equal ivars' do
  74
+        array = [Equality.new('foo', 'bar'), Equality.new('foo', 'bar')]
  75
+        assert_equal 1, array.uniq.size
  76
+      end
  77
+
  78
+      it 'is not equal with different ivars' do
  79
+        array = [Equality.new('foo', 'bar'), Equality.new('foo', 'baz')]
  80
+        assert_equal 2, array.uniq.size
  81
+      end
72 82
     end
73 83
   end
74 84
 end
14  test/nodes/test_extract.rb
@@ -16,4 +16,18 @@
16 16
       }
17 17
     end
18 18
   end
  19
+
  20
+  describe 'equality' do
  21
+    it 'is equal with equal ivars' do
  22
+      table = Arel::Table.new :users
  23
+      array = [table[:attr].extract('foo'), table[:attr].extract('foo')]
  24
+      assert_equal 1, array.uniq.size
  25
+    end
  26
+
  27
+    it 'is not equal with different ivars' do
  28
+      table = Arel::Table.new :users
  29
+      array = [table[:attr].extract('foo'), table[:attr].extract('bar')]
  30
+      assert_equal 2, array.uniq.size
  31
+    end
  32
+  end
19 33
 end
20  test/nodes/test_false.rb
... ...
@@ -0,0 +1,20 @@
  1
+require 'helper'
  2
+
  3
+module Arel
  4
+  module Nodes
  5
+    describe 'False' do
  6
+      describe 'equality' do
  7
+        it 'is equal to other false nodes' do
  8
+          array = [False.new, False.new]
  9
+          assert_equal 1, array.uniq.size
  10
+        end
  11
+
  12
+        it 'is not equal with other nodes' do
  13
+          array = [False.new, Node.new]
  14
+          assert_equal 2, array.uniq.size
  15
+        end
  16
+      end
  17
+    end
  18
+  end
  19
+end
  20
+
12  test/nodes/test_grouping.rb
@@ -7,6 +7,18 @@ module Nodes
7 7
         grouping = Grouping.new('foo')
8 8
         grouping.eq('foo').to_sql.must_be_like %q{('foo') = 'foo'}
9 9
       end
  10
+
  11
+      describe 'equality' do
  12
+        it 'is equal with equal ivars' do
  13
+          array = [Grouping.new('foo'), Grouping.new('foo')]
  14
+          assert_equal 1, array.uniq.size
  15
+        end
  16
+
  17
+        it 'is not equal with different ivars' do
  18
+          array = [Grouping.new('foo'), Grouping.new('bar')]
  19
+          assert_equal 2, array.uniq.size
  20
+        end
  21
+      end
10 22
     end
11 23
   end
12 24
 end
10  test/nodes/test_infix_operation.rb
@@ -25,6 +25,16 @@ def test_opertaion_ordering
25 25
         assert_equal operation, ordering.expr
26 26
         assert ordering.descending?
27 27
       end
  28
+
  29
+      def test_equality_with_same_ivars
  30
+        array = [InfixOperation.new(:+, 1, 2), InfixOperation.new(:+, 1, 2)]
  31
+        assert_equal 1, array.uniq.size
  32
+      end
  33
+
  34
+      def test_inequality_with_different_ivars
  35
+        array = [InfixOperation.new(:+, 1, 2), InfixOperation.new(:+, 1, 3)]
  36
+        assert_equal 2, array.uniq.size
  37
+      end
28 38
     end
29 39
   end
30 40
 end
24  test/nodes/test_insert_statement.rb
@@ -15,4 +15,28 @@
15 15
       dolly.values.wont_be_same_as statement.values
16 16
     end
17 17
   end
  18
+
  19
+  describe 'equality' do
  20
+    it 'is equal with equal ivars' do
  21
+      statement1 = Arel::Nodes::InsertStatement.new
  22
+      statement1.columns = %w[a b c]
  23
+      statement1.values  = %w[x y z]
  24
+      statement2 = Arel::Nodes::InsertStatement.new
  25
+      statement2.columns = %w[a b c]
  26
+      statement2.values  = %w[x y z]
  27
+      array = [statement1, statement2]
  28
+      assert_equal 1, array.uniq.size
  29
+    end
  30
+
  31
+    it 'is not equal with different ivars' do
  32
+      statement1 = Arel::Nodes::InsertStatement.new
  33
+      statement1.columns = %w[a b c]
  34
+      statement1.values  = %w[x y z]
  35
+      statement2 = Arel::Nodes::InsertStatement.new
  36
+      statement2.columns = %w[a b c]
  37
+      statement2.values  = %w[1 2 3]
  38
+      array = [statement1, statement2]
  39
+      assert_equal 2, array.uniq.size
  40
+    end
  41
+  end
18 42
 end
16  test/nodes/test_named_function.rb
@@ -25,6 +25,22 @@ def test_construct_with_alias
25 25
         assert_kind_of SqlLiteral, function.alias
26 26
         assert_equal 'wth', function.alias
27 27
       end
  28
+
  29
+      def test_equality_with_same_ivars
  30
+        array = [
  31
+          NamedFunction.new('omg', 'zomg', 'wth'),
  32
+          NamedFunction.new('omg', 'zomg', 'wth')
  33
+        ]
  34
+        assert_equal 1, array.uniq.size
  35
+      end
  36
+
  37
+      def test_inequality_with_different_ivars
  38
+        array = [
  39
+          NamedFunction.new('omg', 'zomg', 'wth'),
  40
+          NamedFunction.new('zomg', 'zomg', 'wth')
  41
+        ]
  42
+        assert_equal 2, array.uniq.size
  43
+      end
28 44
     end
29 45
   end
30 46
 end
12  test/nodes/test_not.rb
@@ -12,6 +12,18 @@ module Nodes
12 12
           node.expr.must_equal expr
13 13
         end
14 14
       end
  15
+
  16
+      describe 'equality' do
  17
+        it 'is equal with equal ivars' do
  18
+          array = [Not.new('foo'), Not.new('foo')]
  19
+          assert_equal 1, array.uniq.size
  20
+        end
  21
+
  22
+        it 'is not equal with different ivars' do
  23
+          array = [Not.new('foo'), Not.new('baz')]
  24
+          assert_equal 2, array.uniq.size
  25
+        end
  26
+      end
15 27
     end
16 28
   end
17 29
 end
12  test/nodes/test_or.rb
@@ -17,6 +17,18 @@ module Nodes
17 17
           oror.expr.right.must_equal right
18 18
         end
19 19
       end
  20
+
  21
+      describe 'equality' do
  22
+        it 'is equal with equal ivars' do
  23
+          array = [Or.new('foo', 'bar'), Or.new('foo', 'bar')]
  24
+          assert_equal 1, array.uniq.size
  25
+        end
  26
+
  27
+        it 'is not equal with different ivars' do
  28
+          array = [Or.new('foo', 'bar'), Or.new('foo', 'baz')]
  29
+          assert_equal 2, array.uniq.size
  30
+        end
  31
+      end
20 32
     end
21 33
   end
22 34
 end
18  test/nodes/test_over.rb
@@ -46,4 +46,22 @@
46 46
       }
47 47
     end
48 48
   end
  49
+
  50
+  describe 'equality' do
  51
+    it 'is equal with equal ivars' do
  52
+      array = [
  53
+        Arel::Nodes::Over.new('foo', 'bar'),
  54
+        Arel::Nodes::Over.new('foo', 'bar')
  55
+      ]
  56
+      assert_equal 1, array.uniq.size
  57
+    end
  58
+
  59
+    it 'is not equal with different ivars' do
  60
+      array = [
  61
+        Arel::Nodes::Over.new('foo', 'bar'),
  62
+        Arel::Nodes::Over.new('foo', 'baz')
  63
+      ]
  64
+      assert_equal 2, array.uniq.size
  65
+    end
  66
+  end
49 67
 end
38  test/nodes/test_select_core.rb
@@ -26,6 +26,44 @@ def test_set_quantifier
26 26
         viz = Arel::Visitors::ToSql.new Table.engine.connection_pool
27 27
         assert_match 'DISTINCT', viz.accept(core)
28 28
       end
  29
+
  30
+      def test_equality_with_same_ivars
  31
+        core1 = SelectCore.new
  32
+        core1.froms       = %w[a b c]
  33
+        core1.projections = %w[d e f]
  34
+        core1.wheres      = %w[g h i]
  35
+        core1.groups      = %w[j k l]
  36
+        core1.windows     = %w[m n o]
  37
+        core1.having      = %w[p q r]
  38
+        core2 = SelectCore.new
  39
+        core2.froms       = %w[a b c]
  40
+        core2.projections = %w[d e f]
  41
+        core2.wheres      = %w[g h i]
  42
+        core2.groups      = %w[j k l]
  43
+        core2.windows     = %w[m n o]
  44
+        core2.having      = %w[p q r]
  45
+        array = [core1, core2]
  46
+        assert_equal 1, array.uniq.size
  47
+      end
  48
+
  49
+      def test_inequality_with_different_ivars
  50
+        core1 = SelectCore.new
  51
+        core1.froms       = %w[a b c]
  52
+        core1.projections = %w[d e f]
  53
+        core1.wheres      = %w[g h i]
  54
+        core1.groups      = %w[j k l]
  55
+        core1.windows     = %w[m n o]
  56
+        core1.having      = %w[p q r]
  57
+        core2 = SelectCore.new
  58
+        core2.froms       = %w[a b c]
  59
+        core2.projections = %w[d e f]
  60
+        core2.wheres      = %w[g h i]
  61
+        core2.groups      = %w[j k l]
  62
+        core2.windows     = %w[m n o]
  63
+        core2.having      = %w[l o l]
  64
+        array = [core1, core2]
  65
+        assert_equal 2, array.uniq.size
  66
+      end
29 67
     end
30 68
   end
31 69
 end
36  test/nodes/test_select_statement.rb
@@ -10,4 +10,40 @@
10 10
       dolly.cores.wont_be_same_as statement.cores
11 11
     end
12 12
   end
  13
+
  14
+  describe 'equality' do
  15
+    it 'is equal with equal ivars' do
  16
+      statement1 = Arel::Nodes::SelectStatement.new %w[a b c]
  17
+      statement1.offset = 1
  18
+      statement1.limit  = 2
  19
+      statement1.lock   = false
  20
+      statement1.orders = %w[x y z]
  21
+      statement1.with   = 'zomg'
  22
+      statement2 = Arel::Nodes::SelectStatement.new %w[a b c]
  23
+      statement2.offset = 1
  24
+      statement2.limit  = 2
  25
+      statement2.lock   = false
  26
+      statement2.orders = %w[x y z]
  27
+      statement2.with   = 'zomg'
  28
+      array = [statement1, statement2]
  29
+      assert_equal 1, array.uniq.size
  30
+    end
  31
+
  32
+    it 'is not equal with different ivars' do
  33
+      statement1 = Arel::Nodes::SelectStatement.new %w[a b c]
  34
+      statement1.offset = 1
  35
+      statement1.limit  = 2
  36
+      statement1.lock   = false
  37
+      statement1.orders = %w[x y z]
  38
+      statement1.with   = 'zomg'
  39
+      statement2 = Arel::Nodes::SelectStatement.new %w[a b c]
  40
+      statement2.offset = 1
  41
+      statement2.limit  = 2
  42
+      statement2.lock   = false
  43
+      statement2.orders = %w[x y z]
  44
+      statement2.with   = 'wth'
  45
+      array = [statement1, statement2]
  46
+      assert_equal 2, array.uniq.size
  47
+    end
  48
+  end
13 49
 end
10  test/nodes/test_sql_literal.rb
@@ -31,6 +31,16 @@ module Nodes
31 31
           node = SqlLiteral.new('foo').eq(1)
32 32
           @visitor.accept(node).must_be_like %{ foo = 1 }
33 33
         end
  34
+
  35
+        it 'is equal with equal contents' do
  36
+          array = [SqlLiteral.new('foo'), SqlLiteral.new('foo')]
  37
+          assert_equal 1, array.uniq.size
  38
+        end
  39
+
  40
+        it 'is not equal with different contents' do
  41
+          array = [SqlLiteral.new('foo'), SqlLiteral.new('bar')]
  42
+          assert_equal 2, array.uniq.size
  43
+        end
34 44
       end
35 45
 
36 46
       describe 'grouped "or" equality' do
12  test/nodes/test_sum.rb
@@ -9,4 +9,16 @@
9 9
       }
10 10
     end
11 11
   end
  12
+
  13
+  describe 'equality' do
  14
+    it 'is equal with equal ivars' do
  15
+      array = [Arel::Nodes::Sum.new('foo'), Arel::Nodes::Sum.new('foo')]
  16
+      assert_equal 1, array.uniq.size
  17
+    end
  18
+
  19
+    it 'is not equal with different ivars' do
  20
+      array = [Arel::Nodes::Sum.new('foo'), Arel::Nodes::Sum.new('foo!')]
  21
+      assert_equal 2, array.uniq.size
  22
+    end
  23
+  end
12 24
 end
24  test/nodes/test_table_alias.rb
@@ -5,12 +5,32 @@ module Arel
5 5
   module Nodes
6 6
     describe 'table alias' do
7 7
       it 'has an #engine which delegates to the relation' do
8  
-        engine   = Object.new
9  
-        relation = OpenStruct.new(:engine => engine)
  8
+        engine   = 'vroom'
  9
+        relation = Table.new(:users, engine)
10 10
 
11 11
         node = TableAlias.new relation, :foo
12 12
         node.engine.must_equal engine
13 13
       end
  14
+
  15
+      describe 'equality' do
  16
+        it 'is equal with equal ivars' do
  17
+          relation1 = Table.new(:users, 'vroom')
  18
+          node1     = TableAlias.new relation1, :foo
  19
+          relation2 = Table.new(:users, 'vroom')
  20
+          node2     = TableAlias.new relation2, :foo
  21
+          array = [node1, node2]
  22
+          assert_equal 1, array.uniq.size
  23
+        end
  24
+
  25
+        it 'is not equal with different ivars' do
  26
+          relation1 = Table.new(:users, 'vroom')
  27
+          node1     = TableAlias.new relation1, :foo
  28
+          relation2 = Table.new(:users, 'vroom')
  29
+          node2     = TableAlias.new relation2, :bar
  30
+          array = [node1, node2]
  31
+          assert_equal 2, array.uniq.size
  32
+        end
  33
+      end
14 34
     end
15 35
   end
16 36
 end
21  test/nodes/test_true.rb
... ...
@@ -0,0 +1,21 @@
  1
+require 'helper'
  2
+
  3
+module Arel
  4
+  module Nodes
  5
+    describe 'True' do
  6
+      describe 'equality' do
  7
+        it 'is equal to other true nodes' do
  8
+          array = [True.new, True.new]
  9
+          assert_equal 1, array.uniq.size
  10
+        end
  11
+
  12
+        it 'is not equal with other nodes' do
  13
+          array = [True.new, Node.new]
  14
+          assert_equal 2, array.uniq.size
  15
+        end
  16
+      end
  17
+    end
  18
+  end
  19
+end
  20
+
  21
+
40  test/nodes/test_update_statement.rb
@@ -15,4 +15,44 @@
15 15
       dolly.values.wont_be_same_as statement.values
16 16
     end
17 17
   end
  18
+
  19
+  describe 'equality' do
  20
+    it 'is equal with equal ivars' do
  21
+      statement1 = Arel::Nodes::UpdateStatement.new
  22
+      statement1.relation = 'zomg'
  23
+      statement1.wheres   = 2
  24
+      statement1.values   = false
  25
+      statement1.orders   = %w[x y z]
  26
+      statement1.limit    = 42
  27
+      statement1.key      = 'zomg'
  28
+      statement2 = Arel::Nodes::UpdateStatement.new
  29
+      statement2.relation = 'zomg'
  30
+      statement2.wheres   = 2
  31
+      statement2.values   = false
  32
+      statement2.orders   = %w[x y z]
  33
+      statement2.limit    = 42
  34
+      statement2.key      = 'zomg'
  35
+      array = [statement1, statement2]
  36
+      assert_equal 1, array.uniq.size
  37
+    end
  38
+
  39
+    it 'is not equal with different ivars' do
  40
+      statement1 = Arel::Nodes::UpdateStatement.new
  41
+      statement1.relation = 'zomg'
  42
+      statement1.wheres   = 2
  43
+      statement1.values   = false
  44
+      statement1.orders   = %w[x y z]
  45
+      statement1.limit    = 42
  46
+      statement1.key      = 'zomg'
  47
+      statement2 = Arel::Nodes::UpdateStatement.new
  48
+      statement2.relation = 'zomg'
  49
+      statement2.wheres   = 2
  50
+      statement2.values   = false
  51
+      statement2.orders   = %w[x y z]
  52
+      statement2.limit    = 42
  53
+      statement2.key      = 'wth'
  54
+      array = [statement1, statement2]
  55
+      assert_equal 2, array.uniq.size
  56
+    end
  57
+  end
18 58
 end
73  test/nodes/test_window.rb
... ...
@@ -0,0 +1,73 @@
  1
+require 'helper'
  2
+
  3
+module Arel
  4
+  module Nodes
  5
+    describe 'Window' do
  6
+      describe 'equality' do
  7
+        it 'is equal with equal ivars' do
  8
+          window1 = Window.new
  9
+          window1.orders = [1, 2]
  10
+          window1.frame 3
  11
+          window2 = Window.new
  12
+          window2.orders = [1, 2]
  13
+          window2.frame 3
  14
+          array = [window1, window2]
  15
+          assert_equal 1, array.uniq.size
  16
+        end
  17
+
  18
+        it 'is not equal with different ivars' do
  19
+          window1 = Window.new
  20
+          window1.orders = [1, 2]
  21
+          window1.frame 3
  22
+          window2 = Window.new
  23
+          window2.orders = [1, 2]
  24
+          window2.frame 4
  25
+          array = [window1, window2]
  26
+          assert_equal 2, array.uniq.size
  27
+        end
  28
+      end
  29
+    end
  30
+
  31
+    describe 'NamedWindow' do
  32
+      describe 'equality' do
  33
+        it 'is equal with equal ivars' do
  34
+          window1 = NamedWindow.new 'foo'
  35
+          window1.orders = [1, 2]
  36
+          window1.frame 3
  37
+          window2 = NamedWindow.new 'foo'
  38
+          window2.orders = [1, 2]
  39
+          window2.frame 3
  40
+          array = [window1, window2]
  41
+          assert_equal 1, array.uniq.size
  42
+        end
  43
+
  44
+        it 'is not equal with different ivars' do
  45
+          window1 = NamedWindow.new 'foo'
  46
+          window1.orders = [1, 2]
  47
+          window1.frame 3
  48
+          window2 = NamedWindow.new 'bar'
  49
+          window2.orders = [1, 2]
  50
+          window2.frame 3
  51
+          array = [window1, window2]
  52
+          assert_equal 2, array.uniq.size
  53
+        end
  54
+      end
  55
+    end
  56
+
  57
+    describe 'CurrentRow' do
  58
+      describe 'equality' do
  59
+        it 'is equal to other current row nodes' do
  60
+          array = [CurrentRow.new, CurrentRow.new]
  61
+          assert_equal 1, array.uniq.size
  62
+        end
  63
+
  64
+        it 'is not equal with other nodes' do
  65
+          array = [CurrentRow.new, Node.new]
  66
+          assert_equal 2, array.uniq.size
  67
+        end
  68
+      end
  69
+    end
  70
+  end
  71
+end
  72
+
  73
+
12  test/test_attributes.rb
@@ -10,6 +10,18 @@ module Arel
10 10
       assert_equal [attribute], node.expressions
11 11
     end
12 12
 
  13
+    describe 'equality' do
  14
+      it 'is equal with equal ivars' do
  15
+        array = [Attribute.new('foo', 'bar'), Attribute.new('foo', 'bar')]
  16
+        assert_equal 1, array.uniq.size
  17
+      end
  18
+
  19
+      it 'is not equal with different ivars' do
  20
+        array = [Attribute.new('foo', 'bar'), Attribute.new('foo', 'baz')]
  21
+        assert_equal 2, array.uniq.size
  22
+      end
  23
+    end
  24
+
13 25
     describe 'for' do
14 26
       it 'deals with unknown column types' do
15 27
         column = Struct.new(:type).new :crazy
24  test/test_table.rb
@@ -180,5 +180,29 @@ module Arel
180 180
         end
181 181
       end
182 182
     end
  183
+
  184
+    describe 'equality' do
  185
+      it 'is equal with equal ivars' do
  186
+        relation1 = Table.new(:users, 'vroom')
  187
+        relation1.aliases     = %w[a b c]
  188
+        relation1.table_alias = 'zomg'
  189
+        relation2 = Table.new(:users, 'vroom')
  190
+        relation2.aliases     = %w[a b c]
  191
+        relation2.table_alias = 'zomg'
  192
+        array = [relation1, relation2]
  193
+        assert_equal 1, array.uniq.size
  194
+      end
  195
+
  196
+      it 'is not equal with different ivars' do
  197
+        relation1 = Table.new(:users, 'vroom')
  198
+        relation1.aliases     = %w[a b c]
  199
+        relation1.table_alias = 'zomg'
  200
+        relation2 = Table.new(:users, 'vroom')
  201
+        relation2.aliases     = %w[x y z]
  202
+        relation2.table_alias = 'zomg'
  203
+        array = [relation1, relation2]
  204
+        assert_equal 2, array.uniq.size
  205
+      end
  206
+    end
183 207
   end
184 208
 end

0 notes on commit 6e638bb

Please sign in to comment.
Something went wrong with that request. Please try again.