squeel_rbg 0.8.2
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.
- data/.gitignore +4 -0
- data/.yardopts +3 -0
- data/Gemfile +13 -0
- data/LICENSE +20 -0
- data/README.md +398 -0
- data/Rakefile +19 -0
- data/lib/core_ext/hash.rb +13 -0
- data/lib/core_ext/symbol.rb +39 -0
- data/lib/squeel/adapters/active_record/3.0/association_preload.rb +15 -0
- data/lib/squeel/adapters/active_record/3.0/compat.rb +142 -0
- data/lib/squeel/adapters/active_record/3.0/context.rb +66 -0
- data/lib/squeel/adapters/active_record/3.0/join_association.rb +54 -0
- data/lib/squeel/adapters/active_record/3.0/join_dependency.rb +84 -0
- data/lib/squeel/adapters/active_record/3.0/relation.rb +327 -0
- data/lib/squeel/adapters/active_record/context.rb +66 -0
- data/lib/squeel/adapters/active_record/join_association.rb +44 -0
- data/lib/squeel/adapters/active_record/join_dependency.rb +83 -0
- data/lib/squeel/adapters/active_record/preloader.rb +21 -0
- data/lib/squeel/adapters/active_record/relation.rb +351 -0
- data/lib/squeel/adapters/active_record.rb +28 -0
- data/lib/squeel/configuration.rb +54 -0
- data/lib/squeel/constants.rb +24 -0
- data/lib/squeel/context.rb +67 -0
- data/lib/squeel/dsl.rb +86 -0
- data/lib/squeel/nodes/aliasing.rb +13 -0
- data/lib/squeel/nodes/and.rb +9 -0
- data/lib/squeel/nodes/as.rb +14 -0
- data/lib/squeel/nodes/binary.rb +32 -0
- data/lib/squeel/nodes/function.rb +66 -0
- data/lib/squeel/nodes/join.rb +113 -0
- data/lib/squeel/nodes/key_path.rb +192 -0
- data/lib/squeel/nodes/nary.rb +45 -0
- data/lib/squeel/nodes/not.rb +9 -0
- data/lib/squeel/nodes/operation.rb +32 -0
- data/lib/squeel/nodes/operators.rb +43 -0
- data/lib/squeel/nodes/or.rb +9 -0
- data/lib/squeel/nodes/order.rb +53 -0
- data/lib/squeel/nodes/predicate.rb +71 -0
- data/lib/squeel/nodes/predicate_operators.rb +29 -0
- data/lib/squeel/nodes/stub.rb +125 -0
- data/lib/squeel/nodes/unary.rb +28 -0
- data/lib/squeel/nodes.rb +17 -0
- data/lib/squeel/predicate_methods.rb +14 -0
- data/lib/squeel/version.rb +3 -0
- data/lib/squeel/visitors/attribute_visitor.rb +191 -0
- data/lib/squeel/visitors/base.rb +112 -0
- data/lib/squeel/visitors/predicate_visitor.rb +319 -0
- data/lib/squeel/visitors/symbol_visitor.rb +48 -0
- data/lib/squeel/visitors.rb +3 -0
- data/lib/squeel.rb +28 -0
- data/lib/squeel_rbg.rb +5 -0
- data/spec/blueprints/articles.rb +5 -0
- data/spec/blueprints/comments.rb +5 -0
- data/spec/blueprints/notes.rb +3 -0
- data/spec/blueprints/people.rb +4 -0
- data/spec/blueprints/tags.rb +3 -0
- data/spec/console.rb +22 -0
- data/spec/core_ext/symbol_spec.rb +75 -0
- data/spec/helpers/squeel_helper.rb +21 -0
- data/spec/spec_helper.rb +66 -0
- data/spec/squeel/adapters/active_record/context_spec.rb +44 -0
- data/spec/squeel/adapters/active_record/join_association_spec.rb +18 -0
- data/spec/squeel/adapters/active_record/join_dependency_spec.rb +66 -0
- data/spec/squeel/adapters/active_record/relation_spec.rb +627 -0
- data/spec/squeel/dsl_spec.rb +92 -0
- data/spec/squeel/nodes/function_spec.rb +149 -0
- data/spec/squeel/nodes/join_spec.rb +47 -0
- data/spec/squeel/nodes/key_path_spec.rb +100 -0
- data/spec/squeel/nodes/operation_spec.rb +149 -0
- data/spec/squeel/nodes/operators_spec.rb +87 -0
- data/spec/squeel/nodes/order_spec.rb +30 -0
- data/spec/squeel/nodes/predicate_operators_spec.rb +88 -0
- data/spec/squeel/nodes/predicate_spec.rb +50 -0
- data/spec/squeel/nodes/stub_spec.rb +198 -0
- data/spec/squeel/visitors/attribute_visitor_spec.rb +142 -0
- data/spec/squeel/visitors/predicate_visitor_spec.rb +342 -0
- data/spec/squeel/visitors/symbol_visitor_spec.rb +42 -0
- data/spec/support/schema.rb +104 -0
- data/squeel.gemspec +43 -0
- metadata +246 -0
@@ -0,0 +1,342 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Squeel
|
4
|
+
module Visitors
|
5
|
+
describe PredicateVisitor do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@jd = new_join_dependency(Person, {
|
9
|
+
:children => {
|
10
|
+
:children => {
|
11
|
+
:parent => :parent
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}, [])
|
15
|
+
@c = Squeel::Adapters::ActiveRecord::Context.new(@jd)
|
16
|
+
@v = PredicateVisitor.new(@c)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'does not quote Arel::SelectManager values in Predicate nodes' do
|
20
|
+
predicate = Nodes::Predicate.new(Nodes::Function.new(:blah, [1, 2]), :in, Person.select(:id).arel)
|
21
|
+
node = @v.accept(predicate)
|
22
|
+
node.should be_a Arel::Nodes::In
|
23
|
+
node.right.should be_a Arel::Nodes::SelectStatement
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'creates Equality nodes for simple hashes' do
|
27
|
+
predicate = @v.accept(:name => 'Joe')
|
28
|
+
predicate.should be_a Arel::Nodes::Equality
|
29
|
+
predicate.left.name.should eq :name
|
30
|
+
predicate.right.should eq 'Joe'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'creates In nodes for simple hashes with an array as a value' do
|
34
|
+
predicate = @v.accept(:name => ['Joe', 'Bob'])
|
35
|
+
predicate.should be_a Arel::Nodes::In
|
36
|
+
predicate.left.name.should eq :name
|
37
|
+
predicate.right.should eq ['Joe', 'Bob']
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'generates "1=0" when given an empty array value in a hash' do
|
41
|
+
predicate = @v.accept(:id => [])
|
42
|
+
predicate.should be_a Arel::Nodes::SqlLiteral
|
43
|
+
predicate.should eq '1=0'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'generates "1=0" for in predicates when given an empty array value' do
|
47
|
+
predicate = @v.accept(:id.in => [])
|
48
|
+
predicate.should be_a Arel::Nodes::SqlLiteral
|
49
|
+
predicate.should eq '1=0'
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'generates "1=1" for not_in predicates when given an empty array value' do
|
53
|
+
predicate = @v.accept(:id.not_in => [])
|
54
|
+
predicate.should be_a Arel::Nodes::SqlLiteral
|
55
|
+
predicate.should eq '1=1'
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'allows a subquery on the value side of an explicit predicate' do
|
59
|
+
predicate = @v.accept dsl{name.in(Person.select{name}.where{name.in(['Aric Smith', 'Gladyce Kulas'])})}
|
60
|
+
predicate.should be_a Arel::Nodes::In
|
61
|
+
predicate.left.name.should eq :name
|
62
|
+
predicate.right.should be_a Arel::Nodes::SelectStatement
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'allows a subquery on the value side of an implicit predicate' do
|
66
|
+
predicate = @v.accept(:name => Person.select{name}.where{name.in(['Aric Smith', 'Gladyce Kulas'])})
|
67
|
+
predicate.should be_a Arel::Nodes::In
|
68
|
+
predicate.left.name.should eq :name
|
69
|
+
predicate.right.should be_a Arel::Nodes::SelectStatement
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'converts ActiveRecord::Base objects to their id' do
|
73
|
+
predicate = @v.accept(:id => Person.first)
|
74
|
+
predicate.should be_a Arel::Nodes::Equality
|
75
|
+
predicate.left.name.should eq :id
|
76
|
+
predicate.right.should eq 1
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'converts arrays of ActiveRecord::Base objects to their ids' do
|
80
|
+
predicate = @v.accept(:id => [Person.first, Person.last])
|
81
|
+
predicate.should be_a Arel::Nodes::In
|
82
|
+
predicate.left.name.should eq :id
|
83
|
+
predicate.right.should eq [1, 332]
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'creates the node against the proper table for nested hashes' do
|
87
|
+
predicate = @v.accept({
|
88
|
+
:children => {
|
89
|
+
:children => {
|
90
|
+
:parent => {
|
91
|
+
:parent => {
|
92
|
+
:name => 'Joe'
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
})
|
98
|
+
predicate.should be_a Arel::Nodes::Equality
|
99
|
+
predicate.left.relation.table_alias.should eq 'parents_people_2'
|
100
|
+
predicate.right.should eq 'Joe'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'treats keypath keys like nested hashes' do
|
104
|
+
standard = @v.accept({
|
105
|
+
:children => {
|
106
|
+
:children => {
|
107
|
+
:parent => {
|
108
|
+
:parent => {
|
109
|
+
:name => 'Joe'
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
})
|
115
|
+
keypath = @v.accept(Nodes::Stub.new(:children).children.parent.parent.name => 'Joe')
|
116
|
+
keypath.to_sql.should eq standard.to_sql
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'honors absolute keypaths' do
|
120
|
+
standard = @v.accept({
|
121
|
+
:children => {
|
122
|
+
:children => {
|
123
|
+
:name => 'Joe'
|
124
|
+
}
|
125
|
+
}
|
126
|
+
})
|
127
|
+
keypath = @v.accept(dsl{{children => {children => {~children.children.name => 'Joe'}}}})
|
128
|
+
keypath.to_sql.should eq standard.to_sql
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'honors absolute keypaths with only an endpoint' do
|
132
|
+
standard = @v.accept({:name => 'Joe'})
|
133
|
+
keypath = @v.accept(dsl{{children => {children => {~name => 'Joe'}}}})
|
134
|
+
keypath.to_sql.should eq standard.to_sql
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'allows incomplete predicates (missing value) as keys' do
|
138
|
+
standard = @v.accept({
|
139
|
+
:children => {
|
140
|
+
:children => {
|
141
|
+
:parent => {
|
142
|
+
:parent => {
|
143
|
+
:name.matches => 'Joe%'
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
})
|
149
|
+
keypath = @v.accept(Nodes::Stub.new(:children).children.parent.parent.name.matches => 'Joe%')
|
150
|
+
keypath.to_sql.should eq standard.to_sql
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'allows hashes as values with keypath keys' do
|
154
|
+
standard = @v.accept({
|
155
|
+
:children => {
|
156
|
+
:children => {
|
157
|
+
:parent => {
|
158
|
+
:parent => {
|
159
|
+
:name => 'Joe'
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
})
|
165
|
+
keypath = @v.accept(Nodes::Stub.new(:children).children.parent.parent => {:name => 'Joe'})
|
166
|
+
keypath.to_sql.should eq standard.to_sql
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'contextualizes Stub values' do
|
170
|
+
predicate = @v.accept(dsl{{name => name}})
|
171
|
+
predicate.should be_a Arel::Nodes::Equality
|
172
|
+
predicate.right.should be_a Arel::Attribute
|
173
|
+
predicate.to_sql.should match /"people"."name" = "people"."name"/
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'contextualizes Symbol values' do
|
177
|
+
predicate = @v.accept(:name => :name)
|
178
|
+
predicate.should be_a Arel::Nodes::Equality
|
179
|
+
predicate.right.should be_a Arel::Attribute
|
180
|
+
predicate.to_sql.should match /"people"."name" = "people"."name"/
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'contextualizes KeyPath values in hashes' do
|
184
|
+
predicate = @v.accept(dsl{{name => children.name}})
|
185
|
+
predicate.should be_a Arel::Nodes::Equality
|
186
|
+
predicate.right.should be_a Arel::Attribute
|
187
|
+
predicate.to_sql.should match /"people"."name" = "children_people"."name"/
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'contextualizes KeyPath values in predicates' do
|
191
|
+
predicate = @v.accept(dsl{name == children.name})
|
192
|
+
predicate.should be_a Arel::Nodes::Equality
|
193
|
+
predicate.right.should be_a Arel::Attribute
|
194
|
+
predicate.to_sql.should match /"people"."name" = "children_people"."name"/
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'honors an explicit table in string keys' do
|
198
|
+
predicate = @v.accept('things.attribute' => 'retro')
|
199
|
+
predicate.should be_a Arel::Nodes::Equality
|
200
|
+
predicate.to_sql.should match /"things"."attribute" = 'retro'/
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'visits ActiveRecord::Relation values in predicates' do
|
204
|
+
predicate = @v.accept(dsl{id >> Person.select{id}.limit(3).order{id.desc}})
|
205
|
+
predicate.should be_a Arel::Nodes::In
|
206
|
+
predicate.right.should be_a Arel::Nodes::SelectStatement
|
207
|
+
predicate.to_sql.should be_like '"people"."id" IN (SELECT "people"."id" FROM "people" ORDER BY "people"."id" DESC LIMIT 3)'
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'converts ActiveRecord::Relation values in function arguments to their ARel AST' do
|
211
|
+
predicate = @v.accept(dsl{exists(Person.where{name == 'Aric Smith'})})
|
212
|
+
predicate.should be_a Arel::Nodes::NamedFunction
|
213
|
+
predicate.expressions.first.should be_a Arel::Nodes::SelectStatement
|
214
|
+
predicate.to_sql.should be_like "exists(SELECT \"people\".* FROM \"people\" WHERE \"people\".\"name\" = 'Aric Smith')"
|
215
|
+
end
|
216
|
+
|
217
|
+
it "doesn't try to sanitize_sql an array of strings in the value of a Predicate" do
|
218
|
+
predicate = @v.accept(dsl{name >> ['Aric Smith', 'Gladyce Kulas']})
|
219
|
+
predicate.should be_a Arel::Nodes::In
|
220
|
+
predicate.right.should be_an Array
|
221
|
+
predicate.to_sql.should match /"people"."name" IN \('Aric Smith', 'Gladyce Kulas'\)/
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'creates a node of the proper type when a hash has a Predicate as a key' do
|
225
|
+
predicate = @v.accept(:name.matches => 'Joe%')
|
226
|
+
predicate.should be_a Arel::Nodes::Matches
|
227
|
+
predicate.left.name.should eq :name
|
228
|
+
predicate.right.should eq 'Joe%'
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'treats hash keys as an association when there is an Or on the value side' do
|
232
|
+
predicate = @v.accept(:children => (:name.matches % 'Joe%' | :name.matches % 'Bob%'))
|
233
|
+
predicate.should be_a Arel::Nodes::Grouping
|
234
|
+
predicate.expr.should be_a Arel::Nodes::Or
|
235
|
+
predicate.expr.left.should be_a Arel::Nodes::Matches
|
236
|
+
predicate.expr.left.left.relation.table_alias.should eq 'children_people'
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'treats hash keys as an association when there is an And on the value side' do
|
240
|
+
predicate = @v.accept(:children => (:name.matches % 'Joe%' & :name.matches % 'Bob%'))
|
241
|
+
predicate.should be_a Arel::Nodes::Grouping
|
242
|
+
predicate.expr.should be_a Arel::Nodes::And
|
243
|
+
predicate.expr.children.should have(2).items
|
244
|
+
predicate.expr.children.first.should be_a Arel::Nodes::Matches
|
245
|
+
predicate.expr.children.first.left.relation.table_alias.should eq 'children_people'
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'treats hash keys as an association when there is a Not on the value side' do
|
249
|
+
predicate = @v.accept(:children => -(:name.matches % 'Joe%'))
|
250
|
+
predicate.should be_a Arel::Nodes::Not
|
251
|
+
predicate.expr.should be_a Arel::Nodes::Matches
|
252
|
+
predicate.expr.left.relation.table_alias.should eq 'children_people'
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'treats hash keys as an association when there is a Predicate on the value side' do
|
256
|
+
predicate = @v.accept(:children => (:name.matches % 'Joe%'))
|
257
|
+
predicate.should be_a Arel::Nodes::Matches
|
258
|
+
predicate.left.relation.table_alias.should eq 'children_people'
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'treats hash keys as an association when there is a KeyPath on the value side' do
|
262
|
+
predicate = @v.accept(:children => Nodes::Stub.new(:children).name.eq('Joe'))
|
263
|
+
predicate.should be_a Arel::Nodes::Equality
|
264
|
+
predicate.left.relation.table_alias.should eq 'children_people_2'
|
265
|
+
predicate.left.name.should eq :name
|
266
|
+
predicate.right.should eq 'Joe'
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'creates an ARel Grouping node containing an Or node for Or nodes' do
|
270
|
+
left = :name.matches % 'Joe%'
|
271
|
+
right = :id.gt % 1
|
272
|
+
predicate = @v.accept(left | right)
|
273
|
+
predicate.should be_a Arel::Nodes::Grouping
|
274
|
+
predicate.expr.should be_a Arel::Nodes::Or
|
275
|
+
predicate.expr.left.should be_a Arel::Nodes::Matches
|
276
|
+
predicate.expr.right.should be_a Arel::Nodes::GreaterThan
|
277
|
+
end
|
278
|
+
|
279
|
+
it 'creates an ARel Not node for a Not node' do
|
280
|
+
expr = -(:name.matches % 'Joe%')
|
281
|
+
predicate = @v.accept(expr)
|
282
|
+
predicate.should be_a Arel::Nodes::Not
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'creates an ARel NamedFunction node for a Function node' do
|
286
|
+
function = @v.accept(:find_in_set.func())
|
287
|
+
function.should be_a Arel::Nodes::NamedFunction
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'maps symbols in Function args to ARel attributes' do
|
291
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3'))
|
292
|
+
function.to_sql.should match /"people"."id"/
|
293
|
+
end
|
294
|
+
|
295
|
+
it 'sets the alias on the ARel NamedFunction from the Function alias' do
|
296
|
+
function = @v.accept(:find_in_set.func(:id, '1,2,3').as('newname'))
|
297
|
+
function.to_sql.should match /newname/
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'creates an ARel Addition node for an Operation node with + as operator' do
|
301
|
+
operation = @v.accept(dsl{id + 1})
|
302
|
+
operation.should be_a Arel::Nodes::Addition
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'creates an ARel Subtraction node for an Operation node with - as operator' do
|
306
|
+
operation = @v.accept(dsl{id - 1})
|
307
|
+
operation.should be_a Arel::Nodes::Subtraction
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'creates an ARel Multiplication node for an Operation node with * as operator' do
|
311
|
+
operation = @v.accept(dsl{id * 1})
|
312
|
+
operation.should be_a Arel::Nodes::Multiplication
|
313
|
+
end
|
314
|
+
|
315
|
+
it 'creates an ARel Division node for an Operation node with / as operator' do
|
316
|
+
operation = @v.accept(dsl{id / 1})
|
317
|
+
operation.should be_a Arel::Nodes::Division
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'sets the alias on an InfixOperation from the Operation alias' do
|
321
|
+
operation = @v.accept(dsl{(id + 1).as(:incremented_id)})
|
322
|
+
operation.to_sql.should match /incremented_id/
|
323
|
+
end
|
324
|
+
|
325
|
+
context 'with polymorphic joins in the JoinDependency' do
|
326
|
+
before do
|
327
|
+
@jd = new_join_dependency(Note, dsl{[notable(Article), notable(Person)]}, [])
|
328
|
+
@c = Squeel::Adapters::ActiveRecord::Context.new(@jd)
|
329
|
+
@v = PredicateVisitor.new(@c)
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'respects the polymorphic class in conditions' do
|
333
|
+
article_predicate = @v.accept dsl{{notable(Article) => {:title => 'Hello world!'}}}
|
334
|
+
person_predicate = @v.accept dsl{{notable(Person) => {:name => 'Ernie'}}}
|
335
|
+
article_predicate.left.relation.name.should eq 'articles'
|
336
|
+
person_predicate.left.relation.name.should eq 'people'
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Squeel
|
4
|
+
module Visitors
|
5
|
+
describe SymbolVisitor do
|
6
|
+
before do
|
7
|
+
@v = SymbolVisitor.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'returns symbols unmodified' do
|
11
|
+
@v.accept(:blah).should eq :blah
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'converts stubs to symbols' do
|
15
|
+
@v.accept(dsl{blah}).should eq :blah
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'converts joins to their names' do
|
19
|
+
@v.accept(dsl{blah(Article)}).should eq :blah
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'converts keypaths to their hash equivalents' do
|
23
|
+
@v.accept(dsl{one.two.three.four}).should eq({
|
24
|
+
:one => {:two => {:three => :four}}
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'visits hashes' do
|
29
|
+
@v.accept(dsl{{
|
30
|
+
blah1 => {blah2(Article) => blah3}
|
31
|
+
}}).should eq({:blah1 => {:blah2 => :blah3}})
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'visits arrays' do
|
35
|
+
@v.accept(dsl{[{
|
36
|
+
blah1 => {blah2(Article) => blah3}
|
37
|
+
}]}).should eq([{:blah1 => {:blah2 => :blah3}}])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection(
|
4
|
+
:adapter => 'sqlite3',
|
5
|
+
:database => ':memory:'
|
6
|
+
)
|
7
|
+
|
8
|
+
class Person < ActiveRecord::Base
|
9
|
+
belongs_to :parent, :class_name => 'Person', :foreign_key => :parent_id
|
10
|
+
has_many :children, :class_name => 'Person', :foreign_key => :parent_id
|
11
|
+
has_many :articles
|
12
|
+
has_many :articles_with_condition, :class_name => 'Article', :conditions => {:title => 'Condition'}
|
13
|
+
has_many :comments
|
14
|
+
has_many :condition_article_comments, :through => :articles_with_condition, :source => :comments
|
15
|
+
has_many :authored_article_comments, :through => :articles,
|
16
|
+
:source => :comments
|
17
|
+
has_many :notes, :as => :notable
|
18
|
+
end
|
19
|
+
|
20
|
+
class Article < ActiveRecord::Base
|
21
|
+
belongs_to :person
|
22
|
+
has_many :comments
|
23
|
+
has_and_belongs_to_many :tags
|
24
|
+
has_many :notes, :as => :notable
|
25
|
+
has_many :commenters, :through => :comments, :source => :person
|
26
|
+
end
|
27
|
+
|
28
|
+
class Comment < ActiveRecord::Base
|
29
|
+
belongs_to :article
|
30
|
+
belongs_to :person
|
31
|
+
end
|
32
|
+
|
33
|
+
class Tag < ActiveRecord::Base
|
34
|
+
has_and_belongs_to_many :articles
|
35
|
+
end
|
36
|
+
|
37
|
+
class Note < ActiveRecord::Base
|
38
|
+
belongs_to :notable, :polymorphic => true
|
39
|
+
end
|
40
|
+
|
41
|
+
module Schema
|
42
|
+
def self.create
|
43
|
+
ActiveRecord::Base.silence do
|
44
|
+
ActiveRecord::Migration.verbose = false
|
45
|
+
|
46
|
+
ActiveRecord::Schema.define do
|
47
|
+
create_table :people, :force => true do |t|
|
48
|
+
t.integer :parent_id
|
49
|
+
t.string :name
|
50
|
+
t.integer :salary
|
51
|
+
end
|
52
|
+
|
53
|
+
create_table :articles, :force => true do |t|
|
54
|
+
t.integer :person_id
|
55
|
+
t.string :title
|
56
|
+
t.text :body
|
57
|
+
end
|
58
|
+
|
59
|
+
create_table :comments, :force => true do |t|
|
60
|
+
t.integer :article_id
|
61
|
+
t.integer :person_id
|
62
|
+
t.text :body
|
63
|
+
end
|
64
|
+
|
65
|
+
create_table :tags, :force => true do |t|
|
66
|
+
t.string :name
|
67
|
+
end
|
68
|
+
|
69
|
+
create_table :articles_tags, :force => true, :id => false do |t|
|
70
|
+
t.integer :article_id
|
71
|
+
t.integer :tag_id
|
72
|
+
end
|
73
|
+
|
74
|
+
create_table :notes, :force => true do |t|
|
75
|
+
t.integer :notable_id
|
76
|
+
t.string :notable_type
|
77
|
+
t.string :note
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
10.times do
|
84
|
+
person = Person.make
|
85
|
+
Note.make(:notable => person)
|
86
|
+
3.times do
|
87
|
+
article = Article.make(:person => person)
|
88
|
+
3.times do
|
89
|
+
article.tags = [Tag.make, Tag.make, Tag.make]
|
90
|
+
end
|
91
|
+
Note.make(:notable => article)
|
92
|
+
10.times do
|
93
|
+
Comment.make(:article => article)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
2.times do
|
97
|
+
Comment.make(:person => person)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
Comment.make(:body => 'First post!', :article => Article.make(:title => 'Hello, world!'))
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/squeel.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "squeel/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "squeel_rbg"
|
7
|
+
s.version = Squeel::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Russen Guggemos"]
|
10
|
+
s.email = ["rguggemos@berklee.edu"]
|
11
|
+
s.homepage = "http://metautonomo.us/projects/squeel"
|
12
|
+
s.summary = %q{ActiveRecord 3, improved.}
|
13
|
+
s.description = %q{
|
14
|
+
Squeel unlocks the power of ARel in your Rails 3 application with
|
15
|
+
a handy block-based syntax. You can write subqueries, access named
|
16
|
+
functions provided by your RDBMS, and more, all without writing
|
17
|
+
SQL strings.
|
18
|
+
|
19
|
+
I'm trying to push a version of this gem, so that bundler doesn't screw up with the :git included versions.
|
20
|
+
}
|
21
|
+
s.post_install_message = %q{
|
22
|
+
*** Thanks for installing Squeel! ***
|
23
|
+
Be sure to check out http://metautonomo.us/projects/squeel/ for a
|
24
|
+
walkthrough of Squeel's features, and click the donate link if
|
25
|
+
you're feeling especially appreciative. It'd help me justify this
|
26
|
+
"open source" stuff to my lovely wife. :)
|
27
|
+
|
28
|
+
}
|
29
|
+
|
30
|
+
s.rubyforge_project = "squeel_rbg"
|
31
|
+
|
32
|
+
s.add_dependency 'activerecord', '~> 3.0'
|
33
|
+
s.add_dependency 'activesupport', '~> 3.0'
|
34
|
+
s.add_development_dependency 'rspec', '~> 2.5.0'
|
35
|
+
s.add_development_dependency 'machinist', '~> 1.0.6'
|
36
|
+
s.add_development_dependency 'faker', '~> 0.9.5'
|
37
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
38
|
+
|
39
|
+
s.files = `git ls-files`.split("\n")
|
40
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
41
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
end
|