mr 0.35.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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +13 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/bench/all.rb +4 -0
- data/bench/factory.rb +68 -0
- data/bench/fake_record.rb +174 -0
- data/bench/model.rb +201 -0
- data/bench/read_model.rb +191 -0
- data/bench/results/factory.txt +21 -0
- data/bench/results/fake_record.txt +37 -0
- data/bench/results/model.txt +44 -0
- data/bench/results/read_model.txt +46 -0
- data/bench/setup.rb +132 -0
- data/lib/mr.rb +11 -0
- data/lib/mr/after_commit.rb +49 -0
- data/lib/mr/after_commit/fake_record.rb +39 -0
- data/lib/mr/after_commit/record.rb +48 -0
- data/lib/mr/after_commit/record_procs_methods.rb +82 -0
- data/lib/mr/factory.rb +82 -0
- data/lib/mr/factory/config.rb +240 -0
- data/lib/mr/factory/model_factory.rb +103 -0
- data/lib/mr/factory/model_stack.rb +28 -0
- data/lib/mr/factory/read_model_factory.rb +104 -0
- data/lib/mr/factory/record_factory.rb +130 -0
- data/lib/mr/factory/record_stack.rb +219 -0
- data/lib/mr/fake_query.rb +53 -0
- data/lib/mr/fake_record.rb +58 -0
- data/lib/mr/fake_record/associations.rb +257 -0
- data/lib/mr/fake_record/attributes.rb +168 -0
- data/lib/mr/fake_record/persistence.rb +116 -0
- data/lib/mr/json_field.rb +180 -0
- data/lib/mr/json_field/fake_record.rb +31 -0
- data/lib/mr/json_field/record.rb +38 -0
- data/lib/mr/model.rb +67 -0
- data/lib/mr/model/associations.rb +161 -0
- data/lib/mr/model/configuration.rb +67 -0
- data/lib/mr/model/fields.rb +177 -0
- data/lib/mr/model/persistence.rb +79 -0
- data/lib/mr/query.rb +126 -0
- data/lib/mr/read_model.rb +83 -0
- data/lib/mr/read_model/data.rb +38 -0
- data/lib/mr/read_model/fields.rb +218 -0
- data/lib/mr/read_model/query_expression.rb +188 -0
- data/lib/mr/read_model/querying.rb +214 -0
- data/lib/mr/read_model/set_querying.rb +82 -0
- data/lib/mr/read_model/subquery.rb +98 -0
- data/lib/mr/record.rb +35 -0
- data/lib/mr/test_helpers.rb +229 -0
- data/lib/mr/type_converter.rb +85 -0
- data/lib/mr/version.rb +3 -0
- data/log/.gitkeep +0 -0
- data/mr.gemspec +29 -0
- data/test/helper.rb +21 -0
- data/test/support/db.rb +10 -0
- data/test/support/factory.rb +13 -0
- data/test/support/factory/area.rb +6 -0
- data/test/support/factory/comment.rb +14 -0
- data/test/support/factory/image.rb +6 -0
- data/test/support/factory/user.rb +6 -0
- data/test/support/models/area.rb +58 -0
- data/test/support/models/comment.rb +60 -0
- data/test/support/models/image.rb +53 -0
- data/test/support/models/user.rb +96 -0
- data/test/support/read_model/querying.rb +150 -0
- data/test/support/read_models/comment_with_user_data.rb +27 -0
- data/test/support/read_models/set_data.rb +49 -0
- data/test/support/read_models/subquery_data.rb +41 -0
- data/test/support/read_models/user_with_area_data.rb +15 -0
- data/test/support/schema.rb +39 -0
- data/test/support/setup_test_db.rb +10 -0
- data/test/system/factory/model_factory_tests.rb +87 -0
- data/test/system/factory/model_stack_tests.rb +30 -0
- data/test/system/factory/record_factory_tests.rb +84 -0
- data/test/system/factory/record_stack_tests.rb +51 -0
- data/test/system/factory_tests.rb +32 -0
- data/test/system/read_model_tests.rb +199 -0
- data/test/system/with_model_tests.rb +275 -0
- data/test/unit/after_commit/fake_record_tests.rb +110 -0
- data/test/unit/after_commit/record_procs_methods_tests.rb +177 -0
- data/test/unit/after_commit/record_tests.rb +134 -0
- data/test/unit/after_commit_tests.rb +113 -0
- data/test/unit/factory/config_tests.rb +651 -0
- data/test/unit/factory/model_factory_tests.rb +473 -0
- data/test/unit/factory/model_stack_tests.rb +97 -0
- data/test/unit/factory/read_model_factory_tests.rb +195 -0
- data/test/unit/factory/record_factory_tests.rb +446 -0
- data/test/unit/factory/record_stack_tests.rb +549 -0
- data/test/unit/factory_tests.rb +213 -0
- data/test/unit/fake_query_tests.rb +137 -0
- data/test/unit/fake_record/associations_tests.rb +585 -0
- data/test/unit/fake_record/attributes_tests.rb +265 -0
- data/test/unit/fake_record/persistence_tests.rb +239 -0
- data/test/unit/fake_record_tests.rb +106 -0
- data/test/unit/json_field/fake_record_tests.rb +75 -0
- data/test/unit/json_field/record_tests.rb +80 -0
- data/test/unit/json_field_tests.rb +302 -0
- data/test/unit/model/associations_tests.rb +346 -0
- data/test/unit/model/configuration_tests.rb +92 -0
- data/test/unit/model/fields_tests.rb +278 -0
- data/test/unit/model/persistence_tests.rb +114 -0
- data/test/unit/model_tests.rb +137 -0
- data/test/unit/query_tests.rb +300 -0
- data/test/unit/read_model/data_tests.rb +56 -0
- data/test/unit/read_model/fields_tests.rb +416 -0
- data/test/unit/read_model/query_expression_tests.rb +381 -0
- data/test/unit/read_model/querying_tests.rb +613 -0
- data/test/unit/read_model/set_querying_tests.rb +149 -0
- data/test/unit/read_model/subquery_tests.rb +242 -0
- data/test/unit/read_model_tests.rb +187 -0
- data/test/unit/record_tests.rb +45 -0
- data/test/unit/test_helpers_tests.rb +431 -0
- data/test/unit/type_converter_tests.rb +207 -0
- metadata +285 -0
@@ -0,0 +1,381 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/read_model/query_expression'
|
3
|
+
|
4
|
+
require 'ardb/relation_spy'
|
5
|
+
require 'mr/fake_record'
|
6
|
+
require 'mr/read_model/set_querying'
|
7
|
+
require 'test/support/read_model/querying'
|
8
|
+
|
9
|
+
module MR::ReadModel
|
10
|
+
|
11
|
+
class UnitTests < Assert::Context
|
12
|
+
include Querying::TestHelpers
|
13
|
+
desc "MR::ReadModel"
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class QueryExpressionTests < UnitTests
|
18
|
+
desc "QueryExpression"
|
19
|
+
subject{ QueryExpression }
|
20
|
+
|
21
|
+
should "return the correct type of expression using `new`" do
|
22
|
+
expression = subject.new(:select, 'column')
|
23
|
+
assert_instance_of StaticQueryExpression, expression
|
24
|
+
expression = subject.new(:select){ 'column' }
|
25
|
+
assert_instance_of DynamicQueryExpression, expression
|
26
|
+
end
|
27
|
+
|
28
|
+
should "raise an invalid error when not passed args or a block" do
|
29
|
+
assert_raises(InvalidQueryExpressionError){ subject.new(:select) }
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class StaticQueryExpressionTests < UnitTests
|
35
|
+
desc "StaticQueryExpression"
|
36
|
+
setup do
|
37
|
+
@ar_relation = FakeTestRecord.scoped
|
38
|
+
@expression = StaticQueryExpression.new(:select, 'column')
|
39
|
+
end
|
40
|
+
subject{ @expression }
|
41
|
+
|
42
|
+
should have_readers :type, :args
|
43
|
+
|
44
|
+
should "apply itself to an ActiveRecord relation using `apply_to`" do
|
45
|
+
subject.apply_to(@ar_relation)
|
46
|
+
assert_expression_applied @ar_relation, subject.type, *subject.args
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class DynamicQueryExpressionTests < UnitTests
|
52
|
+
desc "DynamicQueryExpression"
|
53
|
+
setup do
|
54
|
+
@ar_relation = FakeTestRecord.scoped
|
55
|
+
block = proc{ 'column' }
|
56
|
+
@expression = DynamicQueryExpression.new(:select, &block)
|
57
|
+
end
|
58
|
+
subject{ @expression }
|
59
|
+
|
60
|
+
should have_readers :type, :block
|
61
|
+
|
62
|
+
should "apply itself to an ActiveRecord relation using `apply_to`" do
|
63
|
+
subject.apply_to(@ar_relation, 'test')
|
64
|
+
assert_expression_applied @ar_relation, subject.type, 'column'
|
65
|
+
end
|
66
|
+
|
67
|
+
should "yield any params to it's block using `apply_to`" do
|
68
|
+
yielded = nil
|
69
|
+
block = proc{ |params| yielded = params }
|
70
|
+
expression = DynamicQueryExpression.new(:select, &block)
|
71
|
+
expression.apply_to(@ar_relation, 'test')
|
72
|
+
assert_equal 'test', yielded
|
73
|
+
end
|
74
|
+
|
75
|
+
should "eval it's block in the ActiveRecord relation's scope using `apply_to`" do
|
76
|
+
scope = nil
|
77
|
+
block = proc{ |params| scope = self }
|
78
|
+
expression = DynamicQueryExpression.new(:select, &block)
|
79
|
+
expression.apply_to(@ar_relation, 'test')
|
80
|
+
assert_equal @ar_relation, scope
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class MergeQueryExpressionTests < UnitTests
|
86
|
+
desc "MergeQueryExpression"
|
87
|
+
setup do
|
88
|
+
@ar_relation = FakeTestRecord.scoped
|
89
|
+
@expression = MergeQueryExpression.new(:order, 'relation')
|
90
|
+
end
|
91
|
+
subject{ @expression }
|
92
|
+
|
93
|
+
should have_readers :type, :query_expression
|
94
|
+
should have_imeths :apply_to
|
95
|
+
|
96
|
+
should "build a query expression for a merge" do
|
97
|
+
query_expression = subject.query_expression
|
98
|
+
assert_instance_of StaticQueryExpression, query_expression
|
99
|
+
assert_equal :merge, query_expression.type
|
100
|
+
assert_equal [ 'relation' ], query_expression.args
|
101
|
+
end
|
102
|
+
|
103
|
+
should "apply it's query expression using `apply_to`" do
|
104
|
+
query_expression = subject.query_expression
|
105
|
+
subject.apply_to(@ar_relation)
|
106
|
+
assert_expression_applied @ar_relation, query_expression.type, 'relation'
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
class SubqueryExpressionTests < UnitTests
|
112
|
+
desc "SubqueryExpression"
|
113
|
+
setup do
|
114
|
+
@expression_class = SubqueryExpression
|
115
|
+
end
|
116
|
+
subject{ @expression_class }
|
117
|
+
|
118
|
+
should "know its types" do
|
119
|
+
exp = {
|
120
|
+
:joins => JoinSubquery
|
121
|
+
}
|
122
|
+
assert_equal exp, subject::TYPES
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
class SubqueryExpressionInitTests < SubqueryExpressionTests
|
128
|
+
desc "when init"
|
129
|
+
setup do
|
130
|
+
@type = @expression_class::TYPES.keys.sample
|
131
|
+
@args = Factory.integer(3).times.map{ Factory.string }
|
132
|
+
@block = proc{ Factory.string }
|
133
|
+
|
134
|
+
subquery_class = @expression_class::TYPES[@type]
|
135
|
+
Assert.stub(subquery_class, :new) do |*args, &block|
|
136
|
+
SubquerySpy.new(*args, &block)
|
137
|
+
end
|
138
|
+
|
139
|
+
@expression = @expression_class.new(@type, *@args, &@block)
|
140
|
+
end
|
141
|
+
subject{ @expression }
|
142
|
+
|
143
|
+
should have_readers :subquery_type, :subquery_args, :subquery_block
|
144
|
+
should have_imeths :type, :subquery
|
145
|
+
|
146
|
+
should "know its subquery attributes" do
|
147
|
+
assert_equal @type, subject.subquery_type
|
148
|
+
assert_equal @args, subject.subquery_args
|
149
|
+
assert_equal @block, subject.subquery_block
|
150
|
+
end
|
151
|
+
|
152
|
+
should "alias its subquery type, to be a compatible query expression" do
|
153
|
+
assert_equal subject.subquery_type, subject.type
|
154
|
+
end
|
155
|
+
|
156
|
+
should "know its subquery" do
|
157
|
+
subquery_spy = subject.subquery
|
158
|
+
assert_instance_of SubquerySpy, subquery_spy
|
159
|
+
assert_equal subject.subquery_args, subquery_spy.args
|
160
|
+
assert_equal subject.subquery_block, subquery_spy.block
|
161
|
+
assert_same subquery_spy, subject.subquery
|
162
|
+
end
|
163
|
+
|
164
|
+
should "apply the subquery's SQL to a relation using `apply_to`" do
|
165
|
+
ar_relation = FakeTestRecord.scoped
|
166
|
+
subject.apply_to(ar_relation)
|
167
|
+
|
168
|
+
subquery_spy = subject.subquery
|
169
|
+
assert_nil subquery_spy.sql_built_with
|
170
|
+
assert_expression_applied ar_relation, subject.type, subquery_spy.built_sql
|
171
|
+
|
172
|
+
params = { Factory.string => Factory.string }
|
173
|
+
ar_relation = FakeTestRecord.scoped
|
174
|
+
subject.apply_to(ar_relation, params)
|
175
|
+
|
176
|
+
subquery_spy = subject.subquery
|
177
|
+
assert_equal params, subquery_spy.sql_built_with
|
178
|
+
assert_expression_applied ar_relation, subject.type, subquery_spy.built_sql
|
179
|
+
end
|
180
|
+
|
181
|
+
should "raise an argument error if a block isn't passed" do
|
182
|
+
assert_raises(ArgumentError){ @expression_class.new(@type, *@args) }
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
class FromExpressionTests < UnitTests
|
188
|
+
desc "FromExpression"
|
189
|
+
setup do
|
190
|
+
@expression_class = FromExpression
|
191
|
+
@from_expression = @expression_class.new(FakeTestRecord)
|
192
|
+
end
|
193
|
+
subject{ @from_expression }
|
194
|
+
|
195
|
+
should have_readers :record_class
|
196
|
+
should have_imeths :ar_relation
|
197
|
+
|
198
|
+
should "know its record class" do
|
199
|
+
assert_equal FakeTestRecord, subject.record_class
|
200
|
+
end
|
201
|
+
|
202
|
+
should "use its record class to build an ar relation" do
|
203
|
+
assert_instance_of Ardb::RelationSpy, subject.ar_relation
|
204
|
+
params = { Factory.string => Factory.string }
|
205
|
+
assert_instance_of Ardb::RelationSpy, subject.ar_relation(params)
|
206
|
+
end
|
207
|
+
|
208
|
+
should "raise an argument error if passed a non MR record class" do
|
209
|
+
assert_raises(ArgumentError){ @expression_class.new(Class.new) }
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
class FromSubqueryExpressionTests < UnitTests
|
215
|
+
desc "FromSubqueryExpression"
|
216
|
+
setup do
|
217
|
+
@expression_class = FromSubqueryExpression
|
218
|
+
@subquery_block = proc do
|
219
|
+
read_model{ from FakeTestRecord }
|
220
|
+
end
|
221
|
+
@from_expression = @expression_class.new(&@subquery_block)
|
222
|
+
end
|
223
|
+
subject{ @from_expression }
|
224
|
+
|
225
|
+
should have_readers :subquery_block
|
226
|
+
should have_imeths :from_subquery, :record_class, :ar_relation
|
227
|
+
|
228
|
+
should "know its subquery block" do
|
229
|
+
assert_equal @subquery_block, subject.subquery_block
|
230
|
+
end
|
231
|
+
|
232
|
+
should "know its from subquery" do
|
233
|
+
subquery = subject.from_subquery
|
234
|
+
assert_instance_of FromSubquery, subquery
|
235
|
+
assert_equal FakeTestRecord, subquery.record_class
|
236
|
+
assert_same subquery, subject.from_subquery
|
237
|
+
end
|
238
|
+
|
239
|
+
should "know its record class" do
|
240
|
+
assert_equal subject.from_subquery.record_class, subject.record_class
|
241
|
+
end
|
242
|
+
|
243
|
+
should "use its from subquery to build an ar relation" do
|
244
|
+
build_sql_called_with = nil
|
245
|
+
from_subquery_sql = Factory.text
|
246
|
+
Assert.stub(subject.from_subquery, :build_sql) do |params|
|
247
|
+
build_sql_called_with = params
|
248
|
+
from_subquery_sql
|
249
|
+
end
|
250
|
+
|
251
|
+
ar_relation_spy = subject.ar_relation
|
252
|
+
assert_instance_of Ardb::RelationSpy, ar_relation_spy
|
253
|
+
assert_nil build_sql_called_with
|
254
|
+
assert_expression_applied ar_relation_spy, :from, from_subquery_sql
|
255
|
+
|
256
|
+
params = { Factory.string => Factory.string }
|
257
|
+
ar_relation_spy = subject.ar_relation(params)
|
258
|
+
assert_instance_of Ardb::RelationSpy, ar_relation_spy
|
259
|
+
assert_equal params, build_sql_called_with
|
260
|
+
assert_expression_applied ar_relation_spy, :from, from_subquery_sql
|
261
|
+
end
|
262
|
+
|
263
|
+
should "raise an argument error if not passed a block" do
|
264
|
+
assert_raises(ArgumentError){ @expression_class.new }
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
class NullFromExpressionTests < UnitTests
|
270
|
+
desc "NullFromExpression"
|
271
|
+
setup do
|
272
|
+
@from_expression = NullFromExpression.new
|
273
|
+
end
|
274
|
+
subject{ @from_expression }
|
275
|
+
|
276
|
+
should have_imeths :record_class, :ar_relation
|
277
|
+
|
278
|
+
should "raise a no from expression error" do
|
279
|
+
assert_raises(NoFromExpressionError){ subject.record_class }
|
280
|
+
assert_raises(NoFromExpressionError){ subject.ar_relation }
|
281
|
+
assert_raises(NoFromExpressionError) do
|
282
|
+
subject.ar_relation(Factory.string => Factory.string)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
class SetExpressionTests < UnitTests
|
289
|
+
desc "SetExpression"
|
290
|
+
setup do
|
291
|
+
@expression_class = SetExpression
|
292
|
+
end
|
293
|
+
subject{ @expression_class }
|
294
|
+
|
295
|
+
should "know its operator SQL" do
|
296
|
+
exp = {
|
297
|
+
:union => 'UNION',
|
298
|
+
:union_all => 'UNION ALL',
|
299
|
+
:intersect => 'INTERSECT',
|
300
|
+
:intersect_all => 'INTERSECT ALL',
|
301
|
+
:except => 'EXCEPT',
|
302
|
+
:except_all => 'EXCEPT ALL'
|
303
|
+
}
|
304
|
+
assert_equal exp, subject::OPERATOR_SQL
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
class SetExpressionInitTests < SetExpressionTests
|
310
|
+
desc "when init"
|
311
|
+
setup do
|
312
|
+
@operator = @expression_class::OPERATOR_SQL.keys.sample
|
313
|
+
column = Factory.string
|
314
|
+
@block = proc do
|
315
|
+
select{ |p| p ? p['column'] : column }
|
316
|
+
from FakeTestRecord
|
317
|
+
end
|
318
|
+
@expression = @expression_class.new(@operator, &@block)
|
319
|
+
end
|
320
|
+
subject{ @expression }
|
321
|
+
|
322
|
+
should have_readers :operator_sql, :read_model_block
|
323
|
+
should have_imeths :read_model_class, :combine_sql
|
324
|
+
|
325
|
+
should "know its attributes" do
|
326
|
+
exp = @expression_class::OPERATOR_SQL[@operator]
|
327
|
+
assert_equal exp, subject.operator_sql
|
328
|
+
assert_equal @block, subject.read_model_block
|
329
|
+
end
|
330
|
+
|
331
|
+
should "know its read model class" do
|
332
|
+
read_model_class = subject.read_model_class
|
333
|
+
assert_includes MR::ReadModel, read_model_class
|
334
|
+
assert_includes MR::ReadModel::SetQuerying, read_model_class
|
335
|
+
assert_equal FakeTestRecord, read_model_class.record_class
|
336
|
+
assert_same read_model_class, subject.read_model_class
|
337
|
+
end
|
338
|
+
|
339
|
+
should "combine SQL with its operator using `combine_sql`" do
|
340
|
+
sql = Factory.text
|
341
|
+
exp = "#{sql} #{subject.operator_sql} " \
|
342
|
+
"#{subject.read_model_class.relation.build_for_all.to_sql.strip}"
|
343
|
+
assert_equal exp, subject.combine_sql(sql)
|
344
|
+
|
345
|
+
params = { 'column' => Factory.string }
|
346
|
+
exp = "#{sql} #{subject.operator_sql} " \
|
347
|
+
"#{subject.read_model_class.build_sql(params)}"
|
348
|
+
assert_equal exp, subject.combine_sql(sql, params)
|
349
|
+
end
|
350
|
+
|
351
|
+
should "raise an argument error if a block isn't passed" do
|
352
|
+
assert_raises(ArgumentError){ @expression_class.new(@type, *@args) }
|
353
|
+
end
|
354
|
+
|
355
|
+
end
|
356
|
+
|
357
|
+
class FakeTestRecord
|
358
|
+
include MR::FakeRecord
|
359
|
+
|
360
|
+
def self.scoped
|
361
|
+
Ardb::RelationSpy.new
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
class SubquerySpy
|
366
|
+
attr_reader :args, :block, :built_sql, :sql_built_with
|
367
|
+
|
368
|
+
def initialize(*args, &block)
|
369
|
+
@args = args
|
370
|
+
@block = block
|
371
|
+
@built_sql = Factory.text
|
372
|
+
@sql_built_with = nil
|
373
|
+
end
|
374
|
+
|
375
|
+
def build_sql(params = nil)
|
376
|
+
@sql_built_with = params
|
377
|
+
@built_sql
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
end
|
@@ -0,0 +1,613 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/read_model/querying'
|
3
|
+
|
4
|
+
require 'ardb/relation_spy'
|
5
|
+
require 'much-plugin'
|
6
|
+
require 'mr/fake_record'
|
7
|
+
require 'mr/fake_query'
|
8
|
+
require 'mr/query'
|
9
|
+
require 'test/support/read_model/querying'
|
10
|
+
|
11
|
+
module MR::ReadModel
|
12
|
+
|
13
|
+
class UnitTests < Assert::Context
|
14
|
+
include MR::ReadModel::Querying::TestHelpers
|
15
|
+
desc "MR::ReadModel"
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class QueryingTests < UnitTests
|
20
|
+
desc "Querying"
|
21
|
+
setup do
|
22
|
+
@read_model_class = Class.new do
|
23
|
+
include MR::ReadModel::Querying
|
24
|
+
attr_reader :data
|
25
|
+
def initialize(data); @data = data; end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
subject{ @read_model_class }
|
29
|
+
|
30
|
+
should have_imeths :relation, :record_class
|
31
|
+
should have_imeths :find, :query, :count, :build_sql, :find_attr
|
32
|
+
should have_imeths :select
|
33
|
+
should have_imeths :from, :joins
|
34
|
+
should have_imeths :where
|
35
|
+
should have_imeths :order
|
36
|
+
should have_imeths :group, :having
|
37
|
+
should have_imeths :limit, :offset
|
38
|
+
should have_imeths :merge
|
39
|
+
should have_imeths :inner_join_subquery
|
40
|
+
should have_imeths :left_outer_join_subquery, :left_join_subquery
|
41
|
+
should have_imeths :right_outer_join_subquery, :right_join_subquery
|
42
|
+
should have_imeths :full_outer_join_subquery, :full_join_subquery
|
43
|
+
|
44
|
+
should "use much-plugin" do
|
45
|
+
assert_includes MuchPlugin, MR::ReadModel::Querying
|
46
|
+
end
|
47
|
+
|
48
|
+
should "return a relation using `relation`" do
|
49
|
+
relation = subject.relation
|
50
|
+
assert_instance_of MR::ReadModel::Relation, relation
|
51
|
+
assert_same relation, subject.relation
|
52
|
+
end
|
53
|
+
|
54
|
+
should "know its record class" do
|
55
|
+
if Factory.boolean
|
56
|
+
subject.from FakeTestRecord
|
57
|
+
else
|
58
|
+
subject.from_subquery do
|
59
|
+
read_model{ from FakeTestRecord }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
assert_equal FakeTestRecord, subject.record_class
|
63
|
+
end
|
64
|
+
|
65
|
+
should "know how to find a specific result" do
|
66
|
+
build_for_find_called_with = nil
|
67
|
+
relation_spy = Ardb::RelationSpy.new
|
68
|
+
Assert.stub(subject.relation, :build_for_find) do |*args|
|
69
|
+
build_for_find_called_with = args
|
70
|
+
relation_spy
|
71
|
+
end
|
72
|
+
|
73
|
+
record = FakeTestRecord.new
|
74
|
+
relation_spy.results << record
|
75
|
+
|
76
|
+
id = Factory.integer
|
77
|
+
result = subject.find(id)
|
78
|
+
assert_equal [id, {}], build_for_find_called_with
|
79
|
+
assert_instance_of subject, result
|
80
|
+
assert_same record, result.data
|
81
|
+
|
82
|
+
params = { Factory.string => Factory.string }
|
83
|
+
result = subject.find(id, params)
|
84
|
+
assert_equal [id, params], build_for_find_called_with
|
85
|
+
assert_instance_of subject, result
|
86
|
+
assert_same record, result.data
|
87
|
+
|
88
|
+
relation_spy.results.clear
|
89
|
+
assert_raises{ subject.find(id) }
|
90
|
+
assert_raises{ subject.find(id, params) }
|
91
|
+
end
|
92
|
+
|
93
|
+
should "know how to build its sql" do
|
94
|
+
build_sql_called_with = nil
|
95
|
+
built_sql = Factory.text
|
96
|
+
Assert.stub(subject.relation, :build_sql) do |params|
|
97
|
+
build_sql_called_with = params
|
98
|
+
built_sql
|
99
|
+
end
|
100
|
+
|
101
|
+
result = subject.build_sql
|
102
|
+
assert_nil build_sql_called_with
|
103
|
+
assert_equal built_sql, result
|
104
|
+
|
105
|
+
params = { Factory.string => Factory.string }
|
106
|
+
result = subject.build_sql(params)
|
107
|
+
assert_equal params, build_sql_called_with
|
108
|
+
assert_equal built_sql, result
|
109
|
+
end
|
110
|
+
|
111
|
+
should "allow setting the relation's find attr" do
|
112
|
+
column = Factory.string
|
113
|
+
subject.find_attr column
|
114
|
+
assert_equal column, subject.relation.find_attr
|
115
|
+
assert_equal column, subject.find_attr
|
116
|
+
end
|
117
|
+
|
118
|
+
should "set the relation's from using `from`" do
|
119
|
+
from_called_with = nil
|
120
|
+
Assert.stub(subject.relation, :from){ |*args| from_called_with = args }
|
121
|
+
|
122
|
+
subject.from FakeTestRecord
|
123
|
+
assert_equal [FakeTestRecord], from_called_with
|
124
|
+
end
|
125
|
+
|
126
|
+
should "set the relation's from subquery using `from_subquery`" do
|
127
|
+
from_subquery_called_with = nil
|
128
|
+
Assert.stub(subject.relation, :from_subquery) do |&block|
|
129
|
+
from_subquery_called_with = block
|
130
|
+
end
|
131
|
+
|
132
|
+
subquery_block = proc{ Factory.string }
|
133
|
+
subject.from_subquery(&subquery_block)
|
134
|
+
assert_equal subquery_block, from_subquery_called_with
|
135
|
+
end
|
136
|
+
|
137
|
+
should "raise an argument error when passing `from` a non MR::Record" do
|
138
|
+
assert_raises(ArgumentError){ subject.from(Class.new) }
|
139
|
+
end
|
140
|
+
|
141
|
+
should "raise an argument error when no block is passed to `from_subquery`" do
|
142
|
+
assert_raises(ArgumentError){ subject.from_subquery }
|
143
|
+
end
|
144
|
+
|
145
|
+
should "raise a no record class error when using the relation before it's configured" do
|
146
|
+
assert_raises(MR::ReadModel::NoFromExpressionError){ subject.query }
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
class WithFromRecordClassTests < QueryingTests
|
152
|
+
setup do
|
153
|
+
@ar_relation_spy = Ardb::RelationSpy.new
|
154
|
+
Assert.stub(FakeTestRecord, :scoped){ @ar_relation_spy }
|
155
|
+
@read_model_class.from FakeTestRecord
|
156
|
+
@relation = @read_model_class.relation
|
157
|
+
end
|
158
|
+
|
159
|
+
should "add a static select to the relation with `select`" do
|
160
|
+
select_sql = "some_table.some_column AS 'something'"
|
161
|
+
subject.select select_sql
|
162
|
+
assert_static_expression_added @relation, :select, select_sql
|
163
|
+
end
|
164
|
+
|
165
|
+
should "add a dynamic select to the relation with `select`" do
|
166
|
+
select_proc = proc{ |name| "some_table.some_column AS '#{name}'" }
|
167
|
+
subject.select(&select_proc)
|
168
|
+
assert_dynamic_expression_added @relation, :select, select_proc
|
169
|
+
end
|
170
|
+
|
171
|
+
should "return the expression using `select`" do
|
172
|
+
select_sql = "some_table.some_column AS 'something'"
|
173
|
+
expression = subject.select select_sql
|
174
|
+
assert_static_expression expression, :select, select_sql
|
175
|
+
end
|
176
|
+
|
177
|
+
should "add a static join to the relation with `joins`" do
|
178
|
+
join_args = [ :some_table, :other_table ]
|
179
|
+
subject.joins(*join_args)
|
180
|
+
assert_static_expression_added @relation, :joins, *join_args
|
181
|
+
end
|
182
|
+
|
183
|
+
should "add a dynamic join to the relation with `joins`" do
|
184
|
+
join_proc = proc{ |name| "CROSS JOIN #{name}" }
|
185
|
+
subject.joins(&join_proc)
|
186
|
+
assert_dynamic_expression_added @relation, :joins, join_proc
|
187
|
+
end
|
188
|
+
|
189
|
+
should "return the expression using `joins`" do
|
190
|
+
join_args = [ :some_table, :other_table ]
|
191
|
+
expression = subject.joins(*join_args)
|
192
|
+
assert_static_expression expression, :joins, join_args
|
193
|
+
end
|
194
|
+
|
195
|
+
should "add a static merge to the relation with `where`" do
|
196
|
+
merge_args = 'fake-relation'
|
197
|
+
subject.where(merge_args)
|
198
|
+
assert_static_merge_expression_added @relation, :where, merge_args
|
199
|
+
end
|
200
|
+
|
201
|
+
should "add a dynamic merge to the relation with `where`" do
|
202
|
+
merge_proc = proc{ 'fake-relation' }
|
203
|
+
subject.where(&merge_proc)
|
204
|
+
assert_dynamic_merge_expression_added @relation, :where, merge_proc
|
205
|
+
end
|
206
|
+
|
207
|
+
should "return the merge expression using `where`" do
|
208
|
+
merge_args = 'fake-relation'
|
209
|
+
expression = subject.where(merge_args)
|
210
|
+
assert_static_merge_expression expression, :where, merge_args
|
211
|
+
end
|
212
|
+
|
213
|
+
should "add a static merge to the relation with `order`" do
|
214
|
+
merge_args = 'fake-relation'
|
215
|
+
subject.order(merge_args)
|
216
|
+
assert_static_merge_expression_added @relation, :order, merge_args
|
217
|
+
end
|
218
|
+
|
219
|
+
should "add a dynamic merge to the relation with `order`" do
|
220
|
+
merge_proc = proc{ 'fake-relation' }
|
221
|
+
subject.order(&merge_proc)
|
222
|
+
assert_dynamic_merge_expression_added @relation, :order, merge_proc
|
223
|
+
end
|
224
|
+
|
225
|
+
should "return the merge expression using `order`" do
|
226
|
+
merge_args = 'fake-relation'
|
227
|
+
expression = subject.order(merge_args)
|
228
|
+
assert_static_merge_expression expression, :order, merge_args
|
229
|
+
end
|
230
|
+
|
231
|
+
should "add a static group to the relation with `group`" do
|
232
|
+
group_args = 'some_table.some_column'
|
233
|
+
subject.group(group_args)
|
234
|
+
assert_static_expression_added @relation, :group, group_args
|
235
|
+
end
|
236
|
+
|
237
|
+
should "add a dynamic group to the relation with `group`" do
|
238
|
+
group_proc = proc{ |column| column }
|
239
|
+
subject.group(&group_proc)
|
240
|
+
assert_dynamic_expression_added @relation, :group, group_proc
|
241
|
+
end
|
242
|
+
|
243
|
+
should "return the expression using `group`" do
|
244
|
+
group_args = 'some_table.some_column'
|
245
|
+
expression = subject.group(group_args)
|
246
|
+
assert_static_expression expression, :group, group_args
|
247
|
+
end
|
248
|
+
|
249
|
+
should "add a static having to the relation with `having`" do
|
250
|
+
having_args = 'COUNT(*) > 0'
|
251
|
+
subject.having(having_args)
|
252
|
+
assert_static_expression_added @relation, :having, having_args
|
253
|
+
end
|
254
|
+
|
255
|
+
should "add a dynamic having to the relation with `having`" do
|
256
|
+
having_proc = proc{ |column| "COUNT(#{column}) > 0" }
|
257
|
+
subject.having(&having_proc)
|
258
|
+
assert_dynamic_expression_added @relation, :having, having_proc
|
259
|
+
end
|
260
|
+
|
261
|
+
should "return the expression using `having`" do
|
262
|
+
having_args = 'COUNT(*) > 0'
|
263
|
+
expression = subject.having(having_args)
|
264
|
+
assert_static_expression expression, :having, having_args
|
265
|
+
end
|
266
|
+
|
267
|
+
should "add a static limit to the relation with `limit`" do
|
268
|
+
limit_args = 1
|
269
|
+
subject.limit(limit_args)
|
270
|
+
assert_static_expression_added @relation, :limit, limit_args
|
271
|
+
end
|
272
|
+
|
273
|
+
should "add a dynamic limit to the relation with `limit`" do
|
274
|
+
limit_proc = proc{ |count| count }
|
275
|
+
subject.limit(&limit_proc)
|
276
|
+
assert_dynamic_expression_added @relation, :limit, limit_proc
|
277
|
+
end
|
278
|
+
|
279
|
+
should "return the expression using `limit`" do
|
280
|
+
limit_args = 1
|
281
|
+
expression = subject.limit(limit_args)
|
282
|
+
assert_static_expression expression, :limit, limit_args
|
283
|
+
end
|
284
|
+
|
285
|
+
should "add a static offset to the relation with `offset`" do
|
286
|
+
offset_args = 1
|
287
|
+
subject.offset(offset_args)
|
288
|
+
assert_static_expression_added @relation, :offset, offset_args
|
289
|
+
end
|
290
|
+
|
291
|
+
should "add a dynamic offset to the relation with `offset`" do
|
292
|
+
offset_proc = proc{ |count| count }
|
293
|
+
subject.offset(&offset_proc)
|
294
|
+
assert_dynamic_expression_added @relation, :offset, offset_proc
|
295
|
+
end
|
296
|
+
|
297
|
+
should "return the expression using `offset`" do
|
298
|
+
offset_args = 1
|
299
|
+
expression = subject.offset(offset_args)
|
300
|
+
assert_static_expression expression, :offset, offset_args
|
301
|
+
end
|
302
|
+
|
303
|
+
should "add a static merge to the relation with `merge`" do
|
304
|
+
merge_args = 'fake-relation'
|
305
|
+
subject.merge(merge_args)
|
306
|
+
assert_static_merge_expression_added @relation, :merge, merge_args
|
307
|
+
end
|
308
|
+
|
309
|
+
should "add a dynamic merge to the relation with `merge`" do
|
310
|
+
merge_proc = proc{ 'fake-relation' }
|
311
|
+
subject.merge(&merge_proc)
|
312
|
+
assert_dynamic_merge_expression_added @relation, :merge, merge_proc
|
313
|
+
end
|
314
|
+
|
315
|
+
should "return the merge expression using `merge`" do
|
316
|
+
merge_args = 'fake-relation'
|
317
|
+
expression = subject.merge(merge_args)
|
318
|
+
assert_static_merge_expression expression, :merge, merge_args
|
319
|
+
end
|
320
|
+
|
321
|
+
should "add a join subquery to the relation with `inner_join_subquery`" do
|
322
|
+
subquery_proc = proc{ as('my_table') }
|
323
|
+
expression = subject.inner_join_subquery(&subquery_proc)
|
324
|
+
assert_inner_join_subquery_added @relation, subquery_proc
|
325
|
+
end
|
326
|
+
|
327
|
+
should "return the subquery expression using `inner_join_subquery`" do
|
328
|
+
subquery_proc = proc{ as('my_table') }
|
329
|
+
expression = subject.inner_join_subquery(&subquery_proc)
|
330
|
+
assert_join_subquery_expression expression, :inner, subquery_proc
|
331
|
+
end
|
332
|
+
|
333
|
+
should "add a join subquery to the relation with `left_outer_join_subquery`" do
|
334
|
+
subquery_proc = proc{ as('my_table') }
|
335
|
+
expression = subject.left_outer_join_subquery(&subquery_proc)
|
336
|
+
assert_left_outer_join_subquery_added @relation, subquery_proc
|
337
|
+
end
|
338
|
+
|
339
|
+
should "return the subquery expression using `left_outer_join_subquery`" do
|
340
|
+
subquery_proc = proc{ as('my_table') }
|
341
|
+
expression = subject.left_outer_join_subquery(&subquery_proc)
|
342
|
+
assert_join_subquery_expression expression, :left, subquery_proc
|
343
|
+
end
|
344
|
+
|
345
|
+
should "add a join subquery to the relation with `right_outer_join_subquery`" do
|
346
|
+
subquery_proc = proc{ as('my_table') }
|
347
|
+
expression = subject.right_outer_join_subquery(&subquery_proc)
|
348
|
+
assert_right_outer_join_subquery_added @relation, subquery_proc
|
349
|
+
end
|
350
|
+
|
351
|
+
should "return the subquery expression using `right_outer_join_subquery`" do
|
352
|
+
subquery_proc = proc{ as('my_table') }
|
353
|
+
expression = subject.right_outer_join_subquery(&subquery_proc)
|
354
|
+
assert_join_subquery_expression expression, :right, subquery_proc
|
355
|
+
end
|
356
|
+
|
357
|
+
should "add a join subquery to the relation with `full_outer_join_subquery`" do
|
358
|
+
subquery_proc = proc{ as('my_table') }
|
359
|
+
expression = subject.full_outer_join_subquery(&subquery_proc)
|
360
|
+
assert_full_outer_join_subquery_added @relation, subquery_proc
|
361
|
+
end
|
362
|
+
|
363
|
+
should "return the subquery expression using `full_outer_join_subquery`" do
|
364
|
+
subquery_proc = proc{ as('my_table') }
|
365
|
+
expression = subject.full_outer_join_subquery(&subquery_proc)
|
366
|
+
assert_join_subquery_expression expression, :full, subquery_proc
|
367
|
+
end
|
368
|
+
|
369
|
+
should "raise an argument error when any query method isn't provided args or a block" do
|
370
|
+
assert_raises(ArgumentError){ subject.select }
|
371
|
+
assert_raises(ArgumentError){ subject.joins }
|
372
|
+
assert_raises(ArgumentError){ subject.where }
|
373
|
+
assert_raises(ArgumentError){ subject.order }
|
374
|
+
assert_raises(ArgumentError){ subject.group }
|
375
|
+
assert_raises(ArgumentError){ subject.having }
|
376
|
+
assert_raises(ArgumentError){ subject.limit }
|
377
|
+
assert_raises(ArgumentError){ subject.offset }
|
378
|
+
assert_raises(ArgumentError){ subject.merge }
|
379
|
+
assert_raises(ArgumentError){ subject.inner_join_subquery }
|
380
|
+
assert_raises(ArgumentError){ subject.left_outer_join_subquery }
|
381
|
+
assert_raises(ArgumentError){ subject.right_outer_join_subquery }
|
382
|
+
assert_raises(ArgumentError){ subject.full_outer_join_subquery }
|
383
|
+
end
|
384
|
+
|
385
|
+
end
|
386
|
+
|
387
|
+
class QueryTests < WithFromRecordClassTests
|
388
|
+
desc "query"
|
389
|
+
setup do
|
390
|
+
@read_model_class.select(:name)
|
391
|
+
@query = @read_model_class.query
|
392
|
+
end
|
393
|
+
subject{ @query }
|
394
|
+
|
395
|
+
should "return an instance of an MR::Query for the class and relation" do
|
396
|
+
assert_instance_of MR::Query, subject
|
397
|
+
assert_equal @read_model_class, subject.model_class
|
398
|
+
assert_equal @ar_relation_spy, subject.relation
|
399
|
+
end
|
400
|
+
|
401
|
+
should "have applied the query expressions to the relation" do
|
402
|
+
assert_expression_applied @ar_relation_spy, :select, :name
|
403
|
+
end
|
404
|
+
|
405
|
+
end
|
406
|
+
|
407
|
+
class CountTests < WithFromRecordClassTests
|
408
|
+
desc "count"
|
409
|
+
setup do
|
410
|
+
results = Array.new(Factory.integer(10))
|
411
|
+
@query = MR::FakeQuery.new(results)
|
412
|
+
|
413
|
+
@args = if Factory.boolean
|
414
|
+
[{ Factory.string => Factory.string }]
|
415
|
+
else # should support when query is overidden
|
416
|
+
@read_model_class.class_eval do
|
417
|
+
def self.query(something, something_else)
|
418
|
+
super({
|
419
|
+
:something => something,
|
420
|
+
:something_else => something_else
|
421
|
+
})
|
422
|
+
end
|
423
|
+
end
|
424
|
+
[Factory.string, Factory.string]
|
425
|
+
end
|
426
|
+
|
427
|
+
@query_called_with = nil
|
428
|
+
Assert.stub(@read_model_class, :query) do |*args|
|
429
|
+
@query_called_with = args
|
430
|
+
@query
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
should "know how to return a count for its query" do
|
435
|
+
result = subject.count(*@args)
|
436
|
+
assert_equal @args, @query_called_with
|
437
|
+
assert_equal @query.count, result
|
438
|
+
end
|
439
|
+
|
440
|
+
end
|
441
|
+
|
442
|
+
class RelationTests < UnitTests
|
443
|
+
desc "Relation"
|
444
|
+
setup do
|
445
|
+
@relation_class = MR::ReadModel::Relation
|
446
|
+
@relation = @relation_class.new
|
447
|
+
end
|
448
|
+
subject{ @relation }
|
449
|
+
|
450
|
+
should have_readers :from_expression, :query_expressions
|
451
|
+
should have_writers :find_attr
|
452
|
+
should have_imeths :from, :from_subquery, :from_record_class, :find_attr
|
453
|
+
should have_imeths :build_for_find, :build_for_all, :build_sql
|
454
|
+
|
455
|
+
should "know its find find excluded types" do
|
456
|
+
exp = [:where, :limit, :offset]
|
457
|
+
assert_equal exp, @relation_class::FIND_EXCLUDED_TYPES
|
458
|
+
end
|
459
|
+
|
460
|
+
should "not have a from expression or any expressions by default" do
|
461
|
+
assert_instance_of NullFromExpression, subject.from_expression
|
462
|
+
assert_equal [], subject.query_expressions
|
463
|
+
end
|
464
|
+
|
465
|
+
should "set its from expression using `from`" do
|
466
|
+
subject.from FakeTestRecord
|
467
|
+
|
468
|
+
assert_instance_of FromExpression, subject.from_expression
|
469
|
+
assert_equal FakeTestRecord, subject.from_expression.record_class
|
470
|
+
end
|
471
|
+
|
472
|
+
should "set its from expression using `from_subquery`" do
|
473
|
+
subquery_block = proc{ Factory.string }
|
474
|
+
subject.from_subquery(&subquery_block)
|
475
|
+
|
476
|
+
assert_instance_of FromSubqueryExpression, subject.from_expression
|
477
|
+
assert_equal subquery_block, subject.from_expression.subquery_block
|
478
|
+
end
|
479
|
+
|
480
|
+
should "know how to build its sql" do
|
481
|
+
built_sql = Factory.text
|
482
|
+
relation_spy = Ardb::RelationSpy.new
|
483
|
+
Assert.stub(relation_spy, :to_sql){ " #{built_sql} " }
|
484
|
+
|
485
|
+
build_for_all_called_with = nil
|
486
|
+
Assert.stub(subject, :build_for_all) do |params|
|
487
|
+
build_for_all_called_with = params
|
488
|
+
relation_spy
|
489
|
+
end
|
490
|
+
|
491
|
+
result = subject.build_sql
|
492
|
+
assert_equal built_sql, result
|
493
|
+
assert_nil build_for_all_called_with
|
494
|
+
|
495
|
+
params = { Factory.string => Factory.string }
|
496
|
+
result = subject.build_sql(params)
|
497
|
+
assert_equal built_sql, result
|
498
|
+
assert_equal params, build_for_all_called_with
|
499
|
+
end
|
500
|
+
|
501
|
+
end
|
502
|
+
|
503
|
+
class RelationWithFromTests < RelationTests
|
504
|
+
desc "with a from expression"
|
505
|
+
setup do
|
506
|
+
if Factory.boolean
|
507
|
+
@relation.from FakeTestRecord
|
508
|
+
else
|
509
|
+
@relation.from_subquery do
|
510
|
+
read_model{ from FakeTestRecord }
|
511
|
+
end
|
512
|
+
@relation.find_attr = Factory.string
|
513
|
+
end
|
514
|
+
@from_ar_relation_built_with = nil
|
515
|
+
Assert.stub(@relation.from_expression, :ar_relation) do |params|
|
516
|
+
@from_ar_relation_built_with = params
|
517
|
+
Ardb::RelationSpy.new
|
518
|
+
end
|
519
|
+
@relation.query_expressions << QueryExpression.new(:select, Factory.string)
|
520
|
+
@relation.query_expressions << QueryExpression.new(:order, Factory.string)
|
521
|
+
@relation_class::FIND_EXCLUDED_TYPES.each do |type|
|
522
|
+
@relation.query_expressions << QueryExpression.new(type, Factory.string)
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
should "know its from record class" do
|
527
|
+
assert_equal subject.from_expression.record_class, subject.from_record_class
|
528
|
+
end
|
529
|
+
|
530
|
+
should "know its find attr" do
|
531
|
+
relation = @relation_class.new.tap{ |r| r.from FakeTestRecord }
|
532
|
+
assert_equal relation.from_expression.default_find_attr, relation.find_attr
|
533
|
+
|
534
|
+
column = Factory.string
|
535
|
+
relation.find_attr = column
|
536
|
+
assert_equal column, relation.find_attr
|
537
|
+
|
538
|
+
# we don't allow from subquery expressions to default their from attr so
|
539
|
+
# the user has to manually specify it
|
540
|
+
relation = @relation_class.new
|
541
|
+
relation.from_subquery do
|
542
|
+
read_model{ from FakeTestRecord }
|
543
|
+
end
|
544
|
+
assert_raises(NoFindAttrError){ relation.find_attr }
|
545
|
+
|
546
|
+
relation.find_attr = column
|
547
|
+
assert_equal column, relation.find_attr
|
548
|
+
end
|
549
|
+
|
550
|
+
should "build an activerecord relation for find using `build_for_find`" do
|
551
|
+
id = Factory.integer
|
552
|
+
ar_relation_spy = subject.build_for_find(id)
|
553
|
+
assert_nil @from_ar_relation_built_with
|
554
|
+
subject.query_expressions.each do |e|
|
555
|
+
if !@relation_class::FIND_EXCLUDED_TYPES.include?(e.type)
|
556
|
+
assert_expression_applied ar_relation_spy, e.type, *e.args
|
557
|
+
else
|
558
|
+
assert_not_expression_applied ar_relation_spy, e.type, *e.args
|
559
|
+
end
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
should "return a new relation everytime `build_for_find` is called" do
|
564
|
+
id = Factory.integer
|
565
|
+
ar_relation = subject.build_for_find(id)
|
566
|
+
assert_not_same ar_relation, subject.build_for_find(id)
|
567
|
+
end
|
568
|
+
|
569
|
+
should "apply expressions using the params passed to `build_for_find`" do
|
570
|
+
subject.query_expressions << QueryExpression.new(:select){ |p| p['column'] }
|
571
|
+
|
572
|
+
id = Factory.integer
|
573
|
+
params = { 'column' => Factory.string }
|
574
|
+
ar_relation = subject.build_for_find(id, params)
|
575
|
+
assert_equal params, @from_ar_relation_built_with
|
576
|
+
assert_expression_applied ar_relation, :select, params['column']
|
577
|
+
end
|
578
|
+
|
579
|
+
should "return a relation from the record class using `build_for_all`" do
|
580
|
+
ar_relation_spy = subject.build_for_all
|
581
|
+
assert_nil @from_ar_relation_built_with
|
582
|
+
subject.query_expressions.each do |e|
|
583
|
+
assert_expression_applied ar_relation_spy, e.type, *e.args
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
should "return a new relation everytime `build_for_all` is called" do
|
588
|
+
ar_relation = subject.build_for_all
|
589
|
+
assert_not_same ar_relation, subject.build_for_all
|
590
|
+
end
|
591
|
+
|
592
|
+
should "apply query expressions using the params passed to `build_for_all`" do
|
593
|
+
subject.query_expressions << QueryExpression.new(:select){ |p| p['column'] }
|
594
|
+
params = { 'column' => Factory.string }
|
595
|
+
ar_relation = subject.build_for_all(params)
|
596
|
+
assert_equal params, @from_ar_relation_built_with
|
597
|
+
assert_expression_applied ar_relation, :select, params['column']
|
598
|
+
end
|
599
|
+
|
600
|
+
end
|
601
|
+
|
602
|
+
class FakeTestRecord
|
603
|
+
include MR::FakeRecord
|
604
|
+
|
605
|
+
def self.table_name; @table_name ||= Factory.string; end
|
606
|
+
def self.primary_key; @primary_key ||= Factory.string; end
|
607
|
+
|
608
|
+
def self.scoped
|
609
|
+
Ardb::RelationSpy.new
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
end
|