squeel 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +41 -0
  5. data/Rakefile +19 -0
  6. data/lib/core_ext/hash.rb +13 -0
  7. data/lib/core_ext/symbol.rb +36 -0
  8. data/lib/squeel.rb +26 -0
  9. data/lib/squeel/adapters/active_record.rb +6 -0
  10. data/lib/squeel/adapters/active_record/join_association.rb +90 -0
  11. data/lib/squeel/adapters/active_record/join_dependency.rb +68 -0
  12. data/lib/squeel/adapters/active_record/relation.rb +292 -0
  13. data/lib/squeel/configuration.rb +25 -0
  14. data/lib/squeel/constants.rb +23 -0
  15. data/lib/squeel/contexts/join_dependency_context.rb +74 -0
  16. data/lib/squeel/dsl.rb +31 -0
  17. data/lib/squeel/nodes.rb +10 -0
  18. data/lib/squeel/nodes/and.rb +8 -0
  19. data/lib/squeel/nodes/binary.rb +23 -0
  20. data/lib/squeel/nodes/function.rb +84 -0
  21. data/lib/squeel/nodes/join.rb +51 -0
  22. data/lib/squeel/nodes/key_path.rb +127 -0
  23. data/lib/squeel/nodes/nary.rb +35 -0
  24. data/lib/squeel/nodes/not.rb +8 -0
  25. data/lib/squeel/nodes/operation.rb +23 -0
  26. data/lib/squeel/nodes/operators.rb +27 -0
  27. data/lib/squeel/nodes/or.rb +8 -0
  28. data/lib/squeel/nodes/order.rb +35 -0
  29. data/lib/squeel/nodes/predicate.rb +49 -0
  30. data/lib/squeel/nodes/predicate_operators.rb +17 -0
  31. data/lib/squeel/nodes/stub.rb +113 -0
  32. data/lib/squeel/nodes/unary.rb +22 -0
  33. data/lib/squeel/predicate_methods.rb +22 -0
  34. data/lib/squeel/predicate_methods/function.rb +9 -0
  35. data/lib/squeel/predicate_methods/predicate.rb +11 -0
  36. data/lib/squeel/predicate_methods/stub.rb +9 -0
  37. data/lib/squeel/predicate_methods/symbol.rb +9 -0
  38. data/lib/squeel/version.rb +3 -0
  39. data/lib/squeel/visitors.rb +3 -0
  40. data/lib/squeel/visitors/base.rb +46 -0
  41. data/lib/squeel/visitors/order_visitor.rb +107 -0
  42. data/lib/squeel/visitors/predicate_visitor.rb +179 -0
  43. data/lib/squeel/visitors/select_visitor.rb +103 -0
  44. data/spec/blueprints/articles.rb +5 -0
  45. data/spec/blueprints/comments.rb +5 -0
  46. data/spec/blueprints/notes.rb +3 -0
  47. data/spec/blueprints/people.rb +4 -0
  48. data/spec/blueprints/tags.rb +3 -0
  49. data/spec/console.rb +22 -0
  50. data/spec/core_ext/symbol_spec.rb +68 -0
  51. data/spec/helpers/squeel_helper.rb +5 -0
  52. data/spec/spec_helper.rb +30 -0
  53. data/spec/squeel/adapters/active_record/join_association_spec.rb +18 -0
  54. data/spec/squeel/adapters/active_record/join_depdendency_spec.rb +60 -0
  55. data/spec/squeel/adapters/active_record/relation_spec.rb +437 -0
  56. data/spec/squeel/contexts/join_dependency_context_spec.rb +43 -0
  57. data/spec/squeel/dsl_spec.rb +73 -0
  58. data/spec/squeel/nodes/function_spec.rb +149 -0
  59. data/spec/squeel/nodes/join_spec.rb +27 -0
  60. data/spec/squeel/nodes/key_path_spec.rb +92 -0
  61. data/spec/squeel/nodes/operation_spec.rb +149 -0
  62. data/spec/squeel/nodes/operators_spec.rb +87 -0
  63. data/spec/squeel/nodes/order_spec.rb +30 -0
  64. data/spec/squeel/nodes/predicate_operators_spec.rb +88 -0
  65. data/spec/squeel/nodes/predicate_spec.rb +92 -0
  66. data/spec/squeel/nodes/stub_spec.rb +178 -0
  67. data/spec/squeel/visitors/order_visitor_spec.rb +128 -0
  68. data/spec/squeel/visitors/predicate_visitor_spec.rb +267 -0
  69. data/spec/squeel/visitors/select_visitor_spec.rb +115 -0
  70. data/spec/support/schema.rb +101 -0
  71. data/squeel.gemspec +44 -0
  72. metadata +221 -0
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Operators do
6
+
7
+ [:+, :-, :*, :/].each do |operator|
8
+ describe "#{operator}" do
9
+ it "creates Operations with #{operator} operator from stubs" do
10
+ left = Stub.new(:stubby_mcstubbenstein)
11
+ node = left.send(operator, 1)
12
+ node.should be_an Operation
13
+ node.left.should eq left
14
+ node.operator.should eq operator
15
+ node.right.should eq 1
16
+ end
17
+
18
+ it "creates Operations with #{operator} operator from key paths" do
19
+ left = KeyPath.new(:first, :second)
20
+ node = left.send(operator, 1)
21
+ node.should be_an Operation
22
+ node.left.should eq left
23
+ node.operator.should eq operator
24
+ node.right.should eq 1
25
+ end
26
+
27
+ it "creates Operations with #{operator} operator from functions" do
28
+ left = Function.new(:name, ["arg1", "arg2"])
29
+ node = left.send(operator, 1)
30
+ node.should be_an Operation
31
+ node.left.should eq left
32
+ node.operator.should eq operator
33
+ node.right.should eq 1
34
+ end
35
+
36
+ it "creates Operations with #{operator} operator from operations" do
37
+ left = Stub.new(:stubby_mcstubbenstein) + 1
38
+ node = left.send(operator, 1)
39
+ node.should be_an Operation
40
+ node.left.should eq left
41
+ node.operator.should eq operator
42
+ node.right.should eq 1
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#op' do
48
+ it "creates Operations with custom operator from stubs" do
49
+ left = Stub.new(:stubby_mcstubbenstein)
50
+ node = left.op('||', 1)
51
+ node.should be_an Operation
52
+ node.left.should eq left
53
+ node.operator.should eq '||'
54
+ node.right.should eq 1
55
+ end
56
+
57
+ it "creates Operations with custom operator from key paths" do
58
+ left = KeyPath.new(:first, :second)
59
+ node = left.op('||', 1)
60
+ node.should be_an Operation
61
+ node.left.should eq left
62
+ node.operator.should eq '||'
63
+ node.right.should eq 1
64
+ end
65
+
66
+ it "creates Operations with custom operator from functions" do
67
+ left = Function.new(:name, ["arg1", "arg2"])
68
+ node = left.op('||', 1)
69
+ node.should be_an Operation
70
+ node.left.should eq left
71
+ node.operator.should eq '||'
72
+ node.right.should eq 1
73
+ end
74
+
75
+ it "creates Operations with custom operator from operations" do
76
+ left = Stub.new(:stubby_mcstubbenstein) + 1
77
+ node = left.op('||', 1)
78
+ node.should be_an Operation
79
+ node.left.should eq left
80
+ node.operator.should eq '||'
81
+ node.right.should eq 1
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Order do
6
+
7
+ it 'requires a direction of -1 or 1' do
8
+ expect { Order.new :attribute, 0 }.to raise_error ArgumentError
9
+ end
10
+
11
+ it 'defaults to ascending order' do
12
+ @o = Order.new :attribute
13
+ @o.should be_ascending
14
+ end
15
+
16
+ it 'allows reversal of order' do
17
+ @o = Order.new :attribute, 1
18
+ @o.reverse!
19
+ @o.should be_descending
20
+ end
21
+
22
+ it 'allows setting order' do
23
+ @o = Order.new :attribute
24
+ @o.desc
25
+ @o.should be_descending
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe PredicateOperators do
6
+
7
+ describe '&' do
8
+ it 'creates And nodes from hashes' do
9
+ left = {:name.matches => 'J%'}
10
+ right = {:name.matches => '%e'}
11
+ n = left & right
12
+ n.should be_a And
13
+ n.children.should eq [left, right]
14
+ end
15
+
16
+ it 'creates And nodes from predicates' do
17
+ left = :name.matches % 'J%'
18
+ right = :name.matches % '%e'
19
+ n = left & right
20
+ n.should be_a And
21
+ n.children.should eq [left, right]
22
+ end
23
+
24
+ it 'appends nodes to children from other And nodes' do
25
+ left = :name.matches % 'J%' & :name.matches % '%e'
26
+ right = :id.gt % 0
27
+ expected = left.children + [right]
28
+ left & right
29
+ left.should be_a And
30
+ left.children.should eq expected
31
+ end
32
+ end
33
+
34
+ describe '|' do
35
+ it 'creates Or nodes from hashes' do
36
+ left = {:name.matches => 'J%'}
37
+ right = {:name.matches => '%e'}
38
+ n = left | right
39
+ n.should be_a Or
40
+ n.left.should eq left
41
+ n.right.should eq right
42
+ end
43
+
44
+ it 'creates Or nodes from predicates' do
45
+ left = :name.matches % 'J%'
46
+ right = :name.matches % '%e'
47
+ n = left | right
48
+ n.should be_a Or
49
+ n.left.should eq left
50
+ n.right.should eq right
51
+ end
52
+
53
+ it 'creates Or nodes from other Or nodes' do
54
+ left = :name.matches % 'J%' | :name.matches % '%e'
55
+ right = :id.gt % 0 | :id.lt % 100
56
+ n = left | right
57
+ n.should be_a Or
58
+ n.left.should eq left
59
+ n.right.should eq right
60
+ end
61
+ end
62
+
63
+ describe '-@' do
64
+ it 'creates Not nodes from hashes' do
65
+ expr = {:name => 'Joe'}
66
+ n = - expr
67
+ n.should be_a Not
68
+ n.expr.should eq expr
69
+ end
70
+
71
+ it 'creates Not nodes from predicates' do
72
+ expr = :name.matches % 'J%'
73
+ n = - expr
74
+ n.should be_a Not
75
+ n.expr.should eq expr
76
+ end
77
+
78
+ it 'creates Not nodes from other Not nodes' do
79
+ expr = -(:name.matches % '%e')
80
+ n = - expr
81
+ n.should be_a Not
82
+ n.expr.should eq expr
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Predicate do
6
+
7
+ context 'ARel predicate methods' do
8
+ before do
9
+ @p = Predicate.new(:attribute)
10
+ end
11
+
12
+ Squeel::Constants::PREDICATES.each do |method_name|
13
+ it "creates #{method_name} predicates with no value" do
14
+ predicate = @p.send(method_name)
15
+ predicate.expr.should eq :attribute
16
+ predicate.method_name.should eq method_name
17
+ predicate.value?.should be_false
18
+ end
19
+
20
+ it "creates #{method_name} predicates with a value" do
21
+ predicate = @p.send(method_name, 'value')
22
+ predicate.expr.should eq :attribute
23
+ predicate.method_name.should eq method_name
24
+ predicate.value.should eq 'value'
25
+ end
26
+ end
27
+
28
+ Squeel::Constants::PREDICATE_ALIASES.each do |method_name, aliases|
29
+ aliases.each do |aliaz|
30
+ ['', '_any', '_all'].each do |suffix|
31
+ it "creates #{method_name.to_s + suffix} predicates with no value using the alias #{aliaz.to_s + suffix}" do
32
+ predicate = @p.send(aliaz.to_s + suffix)
33
+ predicate.expr.should eq :attribute
34
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
35
+ predicate.value?.should be_false
36
+ end
37
+
38
+ it "creates #{method_name.to_s + suffix} predicates with a value using the alias #{aliaz.to_s + suffix}" do
39
+ predicate = @p.send((aliaz.to_s + suffix), 'value')
40
+ predicate.expr.should eq :attribute
41
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
42
+ predicate.value.should eq 'value'
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ it 'accepts a value on instantiation' do
50
+ @p = Predicate.new :name, :eq, 'value'
51
+ @p.value.should eq 'value'
52
+ end
53
+
54
+ it 'sets value via accessor' do
55
+ @p = Predicate.new :name, :eq
56
+ @p.value = 'value'
57
+ @p.value.should eq 'value'
58
+ end
59
+
60
+ it 'sets value via %' do
61
+ @p = Predicate.new :name, :eq
62
+ @p % 'value'
63
+ @p.value.should eq 'value'
64
+ end
65
+
66
+ it 'can be inquired for value presence' do
67
+ @p = Predicate.new :name, :eq
68
+ @p.value?.should be_false
69
+ @p.value = 'value'
70
+ @p.value?.should be_true
71
+ end
72
+
73
+ it 'can be ORed with another predicate' do
74
+ left = Predicate.new :name, :eq, 'Joe'
75
+ right = Predicate.new :name, :eq, 'Bob'
76
+ combined = left | right
77
+ combined.should be_a Nodes::Or
78
+ combined.left.should eq left
79
+ combined.right.should eq right
80
+ end
81
+
82
+ it 'can be ANDed with another predicate' do
83
+ left = Predicate.new :name, :eq, 'Joe'
84
+ right = Predicate.new :name, :eq, 'Bob'
85
+ combined = left & right
86
+ combined.should be_a Nodes::And
87
+ combined.children.should eq [left, right]
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ module Squeel
4
+ module Nodes
5
+ describe Stub do
6
+ before do
7
+ @s = Stub.new :attribute
8
+ end
9
+
10
+ it 'hashes like a symbol' do
11
+ @s.hash.should eq :attribute.hash
12
+ end
13
+
14
+ it 'returns its symbol when sent to_sym' do
15
+ @s.to_sym.should eq :attribute
16
+ end
17
+
18
+ it 'returns a string matching its symbol when sent to_s' do
19
+ @s.to_s.should eq 'attribute'
20
+ end
21
+
22
+ it 'merges against matching stubs' do
23
+ hash1 = {Stub.new(:attribute) => 1}
24
+ hash2 = {Stub.new(:attribute) => 2}
25
+ merged = hash1.merge(hash2)
26
+ merged.keys.should have(1).key
27
+ merged[Stub.new(:attribute)].should eq 2
28
+ end
29
+
30
+ Squeel::Constants::PREDICATES.each do |method_name|
31
+ it "creates #{method_name} predicates with no value" do
32
+ predicate = @s.send(method_name)
33
+ predicate.expr.should eq :attribute
34
+ predicate.method_name.should eq method_name
35
+ predicate.value?.should be_false
36
+ end
37
+
38
+ it "creates #{method_name} predicates with a value" do
39
+ predicate = @s.send(method_name, 'value')
40
+ predicate.expr.should eq :attribute
41
+ predicate.method_name.should eq method_name
42
+ predicate.value.should eq 'value'
43
+ end
44
+ end
45
+
46
+ Squeel::Constants::PREDICATE_ALIASES.each do |method_name, aliases|
47
+ aliases.each do |aliaz|
48
+ ['', '_any', '_all'].each do |suffix|
49
+ it "creates #{method_name.to_s + suffix} predicates with no value using the alias #{aliaz.to_s + suffix}" do
50
+ predicate = @s.send(aliaz.to_s + suffix)
51
+ predicate.expr.should eq :attribute
52
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
53
+ predicate.value?.should be_false
54
+ end
55
+
56
+ it "creates #{method_name.to_s + suffix} predicates with a value using the alias #{aliaz.to_s + suffix}" do
57
+ predicate = @s.send((aliaz.to_s + suffix), 'value')
58
+ predicate.expr.should eq :attribute
59
+ predicate.method_name.should eq "#{method_name}#{suffix}".to_sym
60
+ predicate.value.should eq 'value'
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ it 'creates eq predicates with ==' do
67
+ predicate = @s == 1
68
+ predicate.expr.should eq :attribute
69
+ predicate.method_name.should eq :eq
70
+ predicate.value.should eq 1
71
+ end
72
+
73
+ it 'creates not_eq predicates with ^' do
74
+ predicate = @s ^ 1
75
+ predicate.expr.should eq :attribute
76
+ predicate.method_name.should eq :not_eq
77
+ predicate.value.should eq 1
78
+ end
79
+
80
+ it 'creates not_eq predicates with !=' do
81
+ predicate = @s != 1
82
+ predicate.expr.should eq :attribute
83
+ predicate.method_name.should eq :not_eq
84
+ predicate.value.should eq 1
85
+ end if respond_to?('!=')
86
+
87
+ it 'creates in predicates with >>' do
88
+ predicate = @s >> [1,2,3]
89
+ predicate.expr.should eq :attribute
90
+ predicate.method_name.should eq :in
91
+ predicate.value.should eq [1,2,3]
92
+ end
93
+
94
+ it 'creates not_in predicates with <<' do
95
+ predicate = @s << [1,2,3]
96
+ predicate.expr.should eq :attribute
97
+ predicate.method_name.should eq :not_in
98
+ predicate.value.should eq [1,2,3]
99
+ end
100
+
101
+ it 'creates matches predicates with =~' do
102
+ predicate = @s =~ '%bob%'
103
+ predicate.expr.should eq :attribute
104
+ predicate.method_name.should eq :matches
105
+ predicate.value.should eq '%bob%'
106
+ end
107
+
108
+ it 'creates does_not_match predicates with !~' do
109
+ predicate = @s !~ '%bob%'
110
+ predicate.expr.should eq :attribute
111
+ predicate.method_name.should eq :does_not_match
112
+ predicate.value.should eq '%bob%'
113
+ end if respond_to?('!~')
114
+
115
+ it 'creates gt predicates with >' do
116
+ predicate = @s > 1
117
+ predicate.expr.should eq :attribute
118
+ predicate.method_name.should eq :gt
119
+ predicate.value.should eq 1
120
+ end
121
+
122
+ it 'creates gteq predicates with >=' do
123
+ predicate = @s >= 1
124
+ predicate.expr.should eq :attribute
125
+ predicate.method_name.should eq :gteq
126
+ predicate.value.should eq 1
127
+ end
128
+
129
+ it 'creates lt predicates with <' do
130
+ predicate = @s < 1
131
+ predicate.expr.should eq :attribute
132
+ predicate.method_name.should eq :lt
133
+ predicate.value.should eq 1
134
+ end
135
+
136
+ it 'creates lteq predicates with <=' do
137
+ predicate = @s <= 1
138
+ predicate.expr.should eq :attribute
139
+ predicate.method_name.should eq :lteq
140
+ predicate.value.should eq 1
141
+ end
142
+
143
+ it 'creates ascending orders' do
144
+ order = @s.asc
145
+ order.should be_ascending
146
+ end
147
+
148
+ it 'creates descending orders' do
149
+ order = @s.desc
150
+ order.should be_descending
151
+ end
152
+
153
+ it 'creates inner joins' do
154
+ join = @s.inner
155
+ join.should be_a Join
156
+ join.type.should eq Arel::InnerJoin
157
+ end
158
+
159
+ it 'creates outer joins' do
160
+ join = @s.outer
161
+ join.should be_a Join
162
+ join.type.should eq Arel::OuterJoin
163
+ end
164
+
165
+ it 'creates functions with #func' do
166
+ function = @s.func
167
+ function.should be_a Function
168
+ end
169
+
170
+ it 'creates functions with #[]' do
171
+ function = @s[1, 2, 3]
172
+ function.should be_a Function
173
+ function.args.should eq [1, 2, 3]
174
+ end
175
+
176
+ end
177
+ end
178
+ end