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,651 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/factory/config'
|
3
|
+
|
4
|
+
require 'mr/factory/model_factory'
|
5
|
+
require 'mr/factory/record_factory'
|
6
|
+
require 'mr/fake_record'
|
7
|
+
require 'mr/model'
|
8
|
+
|
9
|
+
module MR::Factory::Config
|
10
|
+
|
11
|
+
class UnitTests < Assert::Context
|
12
|
+
desc "MR::Factory::Config"
|
13
|
+
setup do
|
14
|
+
@config_class = Class.new do
|
15
|
+
include MR::Factory::Config
|
16
|
+
end
|
17
|
+
end
|
18
|
+
subject{ @config_class }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class InitTests < UnitTests
|
23
|
+
desc "when init"
|
24
|
+
setup do
|
25
|
+
@object_class = Factory.boolean ? FakeTwoRecord : TestReadModel
|
26
|
+
|
27
|
+
@config = @config_class.new(@object_class)
|
28
|
+
end
|
29
|
+
subject{ @config }
|
30
|
+
|
31
|
+
should have_readers :object_class
|
32
|
+
should have_imeths :apply_args, :set_default_args
|
33
|
+
|
34
|
+
should "know its object class" do
|
35
|
+
assert_equal @object_class, subject.object_class
|
36
|
+
end
|
37
|
+
|
38
|
+
should "know its object builder class" do
|
39
|
+
exp = MR::Factory::Config::ObjectBuilder
|
40
|
+
assert_equal exp, subject.instance_eval{ object_builder_class }
|
41
|
+
end
|
42
|
+
|
43
|
+
should "know how to apply args" do
|
44
|
+
object = @object_class.new
|
45
|
+
|
46
|
+
call_order = 0
|
47
|
+
apply_hash_called_at = nil
|
48
|
+
apply_hash_called_with = nil
|
49
|
+
Assert.stub(ObjectBuilder, :apply_hash) do |*args|
|
50
|
+
apply_hash_called_at = call_order += 1
|
51
|
+
apply_hash_called_with = args
|
52
|
+
end
|
53
|
+
|
54
|
+
apply_proc_called_at = nil
|
55
|
+
apply_proc_called_with = nil
|
56
|
+
Assert.stub(ObjectBuilder, :apply_proc) do |*args, &block|
|
57
|
+
apply_proc_called_at = call_order += 1
|
58
|
+
apply_proc_called_with = args + [block]
|
59
|
+
end
|
60
|
+
|
61
|
+
args_hash = { :name => Factory.string }
|
62
|
+
subject.apply_args(object, args_hash)
|
63
|
+
|
64
|
+
assert_equal 1, apply_hash_called_at
|
65
|
+
exp = [object, subject, args_hash]
|
66
|
+
assert_equal exp, apply_hash_called_with
|
67
|
+
|
68
|
+
assert_nil apply_proc_called_at
|
69
|
+
assert_nil apply_proc_called_with
|
70
|
+
|
71
|
+
call_order = 0
|
72
|
+
apply_hash_called_at = nil
|
73
|
+
apply_hash_called_with = nil
|
74
|
+
|
75
|
+
# should use a default args proc if one is set
|
76
|
+
default_args_proc = proc{ set :name, Factory.string }
|
77
|
+
subject.set_default_args(&default_args_proc)
|
78
|
+
|
79
|
+
subject.apply_args(object, args_hash)
|
80
|
+
|
81
|
+
assert_equal 1, apply_proc_called_at
|
82
|
+
exp = [object, subject, default_args_proc]
|
83
|
+
assert_equal exp, apply_proc_called_with
|
84
|
+
|
85
|
+
assert_equal 2, apply_hash_called_at
|
86
|
+
exp = [object, subject, args_hash]
|
87
|
+
assert_equal exp, apply_hash_called_with
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
class ObjectBuilderTests < UnitTests
|
93
|
+
desc "ObjectBuilder"
|
94
|
+
setup do
|
95
|
+
@object_class = [FakeTwoRecord, FakeTwoModel].sample
|
96
|
+
|
97
|
+
@object = @object_class.new
|
98
|
+
@config = @config_class.new(@object_class)
|
99
|
+
|
100
|
+
@object_builder_class = ObjectBuilder
|
101
|
+
end
|
102
|
+
subject{ @object_builder_class }
|
103
|
+
|
104
|
+
should have_imeths :apply_hash, :apply_proc
|
105
|
+
|
106
|
+
should "know how to apply a hash and proc" do
|
107
|
+
set_names_and_values = []
|
108
|
+
Assert.stub(@object_builder_class, :new).with(@object, @config) do |*args|
|
109
|
+
object_builder = Assert.stub_send(@object_builder_class, :new, @object, @config)
|
110
|
+
Assert.stub(object_builder, :set) do |key, value|
|
111
|
+
set_names_and_values << [key, value]
|
112
|
+
end
|
113
|
+
object_builder
|
114
|
+
end
|
115
|
+
|
116
|
+
hash = Factory.integer(3).times.inject({}) do |h, _|
|
117
|
+
h.merge!(Factory.string => Factory.string)
|
118
|
+
end
|
119
|
+
|
120
|
+
subject.apply_hash(@object, @config, hash)
|
121
|
+
|
122
|
+
exp = hash.map{ |(k, v)| [k, v] }.sort
|
123
|
+
assert_equal exp, set_names_and_values.sort
|
124
|
+
|
125
|
+
set_names_and_values = []
|
126
|
+
|
127
|
+
subject.apply_proc(@object, @config) do
|
128
|
+
hash.each{ |key, value| set(key, value) }
|
129
|
+
end
|
130
|
+
|
131
|
+
exp = hash.map{ |(k, v)| [k, v] }.sort
|
132
|
+
assert_equal exp, set_names_and_values.sort
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
class ObjectBuilderInitTests < ObjectBuilderTests
|
138
|
+
desc "when init"
|
139
|
+
setup do
|
140
|
+
@object_builder = @object_builder_class.new(@object, @config)
|
141
|
+
end
|
142
|
+
subject{ @object_builder }
|
143
|
+
|
144
|
+
should have_imeths :set
|
145
|
+
|
146
|
+
should "know how to set an attribute on its object" do
|
147
|
+
@object.name = Factory.string
|
148
|
+
|
149
|
+
value = [Factory.string, nil].sample
|
150
|
+
subject.set(:name, value)
|
151
|
+
|
152
|
+
assert_equal value, @object.name
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
class WithAssociationsConfigTests < Assert::Context
|
158
|
+
desc "MR::Factory::WithAssociationsConfig"
|
159
|
+
setup do
|
160
|
+
@factory_class, @build_factory_proc = if Factory.boolean
|
161
|
+
[ MR::Factory::RecordFactory,
|
162
|
+
proc{ |rc| MR::Factory::RecordFactory.new(rc) }
|
163
|
+
]
|
164
|
+
else
|
165
|
+
[ MR::Factory::ModelFactory,
|
166
|
+
proc{ |rc| MR::Factory::ModelFactory.new(rc.model_class, rc) }
|
167
|
+
]
|
168
|
+
end
|
169
|
+
|
170
|
+
build_factory_proc = @build_factory_proc
|
171
|
+
@config_class = Class.new do
|
172
|
+
include MR::Factory::WithAssociationsConfig
|
173
|
+
define_method(:build_factory_for_record_class) do |record_class|
|
174
|
+
build_factory_proc.call(record_class)
|
175
|
+
end
|
176
|
+
private :build_factory_for_record_class
|
177
|
+
end
|
178
|
+
end
|
179
|
+
subject{ @config_class }
|
180
|
+
|
181
|
+
should "be a factory config" do
|
182
|
+
assert_includes MR::Factory::Config, subject
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
class WithAssociationsConfigInitTests < WithAssociationsConfigTests
|
188
|
+
desc "when init"
|
189
|
+
setup do
|
190
|
+
@record_class = FakeTwoRecord
|
191
|
+
@config = @config_class.new(@record_class)
|
192
|
+
end
|
193
|
+
subject{ @config }
|
194
|
+
|
195
|
+
should have_imeths :record_class
|
196
|
+
should have_imeths :force_in_stack_association_names, :force_in_stack_association?
|
197
|
+
should have_imeths :default_factories, :association_factories
|
198
|
+
should have_imeths :factories_for, :factory_for, :factory_config_for
|
199
|
+
should have_imeths :record_classes_for, :build_associated_record
|
200
|
+
should have_imeths :add_association_factory
|
201
|
+
|
202
|
+
should "know its record class" do
|
203
|
+
assert_equal @record_class, subject.record_class
|
204
|
+
end
|
205
|
+
|
206
|
+
should "know its force walk association names" do
|
207
|
+
assert_equal [], subject.force_in_stack_association_names
|
208
|
+
end
|
209
|
+
|
210
|
+
should "know if it should force walk an association" do
|
211
|
+
association_name = Factory.string
|
212
|
+
assert_false subject.force_in_stack_association?(association_name)
|
213
|
+
|
214
|
+
subject.force_in_stack_association_names << association_name
|
215
|
+
|
216
|
+
assert_true subject.force_in_stack_association?(association_name)
|
217
|
+
end
|
218
|
+
|
219
|
+
should "know its object builder class" do
|
220
|
+
exp = MR::Factory::WithAssociationsConfig::ObjectBuilder
|
221
|
+
assert_equal exp, subject.instance_eval{ object_builder_class }
|
222
|
+
end
|
223
|
+
|
224
|
+
should "know its default factories" do
|
225
|
+
assert_equal({}, subject.default_factories)
|
226
|
+
|
227
|
+
factory_built_with = []
|
228
|
+
Assert.stub(@factory_class, :new) do |*args|
|
229
|
+
factory_built_with = args
|
230
|
+
Assert.stub_send(@factory_class, :new, *args)
|
231
|
+
end
|
232
|
+
|
233
|
+
factory = subject.default_factories[FakeOneRecord]
|
234
|
+
assert_instance_of @factory_class, factory
|
235
|
+
if @factory_class == MR::Factory::RecordFactory
|
236
|
+
assert_equal [FakeOneRecord], factory_built_with
|
237
|
+
else
|
238
|
+
assert_equal [FakeOneModel, FakeOneRecord], factory_built_with
|
239
|
+
end
|
240
|
+
|
241
|
+
# should cache the factories it builds
|
242
|
+
assert_equal 1, subject.default_factories.size
|
243
|
+
assert_same factory, subject.default_factories[FakeOneRecord]
|
244
|
+
|
245
|
+
# should raise a no record class error if given a `nil` record class
|
246
|
+
assert_raises(MR::Factory::NoRecordClassError) do
|
247
|
+
subject.default_factories[nil]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
should "know its association factories" do
|
252
|
+
assert_equal({}, subject.association_factories)
|
253
|
+
end
|
254
|
+
|
255
|
+
should "know how to add an association factory" do
|
256
|
+
fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
257
|
+
subject.add_association_factory(:fake_one, fake_one_factory)
|
258
|
+
|
259
|
+
assert_true subject.default_factories.key?(FakeOneRecord)
|
260
|
+
assert_equal fake_one_factory, subject.default_factories[FakeOneRecord]
|
261
|
+
|
262
|
+
key = @config_class::AssociationFactoriesKey.new(:fake_one, FakeOneRecord)
|
263
|
+
assert_true subject.association_factories.key?(key)
|
264
|
+
assert_equal [fake_one_factory], subject.association_factories[key]
|
265
|
+
end
|
266
|
+
|
267
|
+
should "configure an association to be force walked when adding a factory for it" do
|
268
|
+
fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
269
|
+
subject.add_association_factory(:fake_one, fake_one_factory)
|
270
|
+
|
271
|
+
assert_not_includes :fake_one, subject.force_in_stack_association_names
|
272
|
+
|
273
|
+
subject.add_association_factory(:fake_one, fake_one_factory, :force_in_stack => true)
|
274
|
+
assert_includes :fake_one, subject.force_in_stack_association_names
|
275
|
+
end
|
276
|
+
|
277
|
+
should "not duplicate force walk associations when adding a factory for it" do
|
278
|
+
fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
279
|
+
assert_empty subject.force_in_stack_association_names
|
280
|
+
|
281
|
+
subject.add_association_factory(:fake_one, fake_one_factory, :force_in_stack => true)
|
282
|
+
assert_equal 1, subject.force_in_stack_association_names.size
|
283
|
+
|
284
|
+
subject.add_association_factory(:fake_one, fake_one_factory, :force_in_stack => true)
|
285
|
+
assert_equal 1, subject.force_in_stack_association_names.size
|
286
|
+
end
|
287
|
+
|
288
|
+
should "not change a default once its set when adding an association factory" do
|
289
|
+
fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
290
|
+
subject.add_association_factory(:fake_one, fake_one_factory)
|
291
|
+
|
292
|
+
other_fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
293
|
+
subject.add_association_factory(:fake_one, other_fake_one_factory)
|
294
|
+
|
295
|
+
default_factory = subject.default_factories[FakeOneRecord]
|
296
|
+
assert_not_equal other_fake_one_factory, default_factory
|
297
|
+
assert_equal fake_one_factory, default_factory
|
298
|
+
end
|
299
|
+
|
300
|
+
should "store all factories added for an association" do
|
301
|
+
fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
302
|
+
subject.add_association_factory(:fake_one, fake_one_factory)
|
303
|
+
|
304
|
+
other_fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
305
|
+
subject.add_association_factory(:fake_one, other_fake_one_factory)
|
306
|
+
|
307
|
+
key = @config_class::AssociationFactoriesKey.new(:fake_one, FakeOneRecord)
|
308
|
+
assert_equal 2, subject.association_factories[key].size
|
309
|
+
assert_includes fake_one_factory, subject.association_factories[key]
|
310
|
+
assert_includes other_fake_one_factory, subject.association_factories[key]
|
311
|
+
end
|
312
|
+
|
313
|
+
should "know how to add a factory for a polymorphic association" do
|
314
|
+
fake_one_factory = @build_factory_proc.call(FakeOneRecord)
|
315
|
+
subject.add_association_factory(:fake_poly, fake_one_factory)
|
316
|
+
|
317
|
+
assert_true subject.default_factories.key?(FakeOneRecord)
|
318
|
+
assert_equal fake_one_factory, subject.default_factories[FakeOneRecord]
|
319
|
+
|
320
|
+
# should add a `nil` record class association factory key
|
321
|
+
key = @config_class::AssociationFactoriesKey.new(:fake_poly)
|
322
|
+
assert_true subject.association_factories.key?(key)
|
323
|
+
assert_equal [fake_one_factory], subject.association_factories[key]
|
324
|
+
|
325
|
+
key = @config_class::AssociationFactoriesKey.new(:fake_poly, FakeOneRecord)
|
326
|
+
assert_true subject.association_factories.key?(key)
|
327
|
+
assert_equal [fake_one_factory], subject.association_factories[key]
|
328
|
+
end
|
329
|
+
|
330
|
+
should "error if adding a factory for an unknown association" do
|
331
|
+
factory = @build_factory_proc.call(FakeOneRecord)
|
332
|
+
|
333
|
+
assert_raises(MR::Factory::NoAssociationError) do
|
334
|
+
subject.add_association_factory(Factory.string, factory)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
should "know how to get factories for an association and record class" do
|
339
|
+
association_name = Factory.boolean ? :fake_one : :fake_poly
|
340
|
+
|
341
|
+
factory = @build_factory_proc.call(FakeOneRecord)
|
342
|
+
subject.add_association_factory(association_name, factory)
|
343
|
+
|
344
|
+
assert_equal [factory], subject.factories_for(association_name, FakeOneRecord)
|
345
|
+
|
346
|
+
other_factory = @build_factory_proc.call(FakeOneRecord)
|
347
|
+
subject.add_association_factory(association_name, other_factory)
|
348
|
+
|
349
|
+
factories = subject.factories_for(association_name, FakeOneRecord)
|
350
|
+
|
351
|
+
assert_equal 2, factories.size
|
352
|
+
assert_includes factory, factories
|
353
|
+
assert_includes other_factory, factories
|
354
|
+
end
|
355
|
+
|
356
|
+
should "return a default factory for an association if one isn't configured" do
|
357
|
+
association_name = Factory.boolean ? :fake_one : :fake_poly
|
358
|
+
|
359
|
+
exp = [subject.default_factories[FakeOneRecord]]
|
360
|
+
assert_equal exp, subject.factories_for(association_name, FakeOneRecord)
|
361
|
+
end
|
362
|
+
|
363
|
+
should "know how to get a factory for an association and record class" do
|
364
|
+
association_name = Factory.boolean ? :fake_one : :fake_poly
|
365
|
+
|
366
|
+
factories = Factory.integer(3).times.map do
|
367
|
+
@build_factory_proc.call(FakeOneRecord)
|
368
|
+
end
|
369
|
+
Assert.stub(subject, :factories_for).with(
|
370
|
+
association_name,
|
371
|
+
FakeOneRecord
|
372
|
+
){ factories }
|
373
|
+
|
374
|
+
factory = factories.sample
|
375
|
+
Assert.stub(factories, :sample){ factory }
|
376
|
+
|
377
|
+
assert_same factory, subject.factory_for(association_name, FakeOneRecord)
|
378
|
+
end
|
379
|
+
|
380
|
+
should "know how to get record classes for an association" do
|
381
|
+
association_name = Factory.boolean ? :fake_one : :fake_poly
|
382
|
+
|
383
|
+
factories = [
|
384
|
+
@build_factory_proc.call(FakeOneRecord),
|
385
|
+
@build_factory_proc.call(FakeThreeRecord)
|
386
|
+
]
|
387
|
+
Assert.stub(subject, :factories_for).with(association_name, nil){ factories }
|
388
|
+
|
389
|
+
exp = factories.map(&:record_class)
|
390
|
+
assert_equal exp, subject.record_classes_for(association_name)
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
class WithAssociationsConfigObjectBuilderTests < WithAssociationsConfigTests
|
396
|
+
desc "ObjectBuilder"
|
397
|
+
setup do
|
398
|
+
@object_builder_class = MR::Factory::WithAssociationsConfig::ObjectBuilder
|
399
|
+
end
|
400
|
+
subject{ @object_builder_class }
|
401
|
+
|
402
|
+
should "be a factory config object builder" do
|
403
|
+
assert subject < MR::Factory::Config::ObjectBuilder
|
404
|
+
end
|
405
|
+
|
406
|
+
end
|
407
|
+
|
408
|
+
class RecordObjectBuilderInitTests < WithAssociationsConfigObjectBuilderTests
|
409
|
+
desc "when init with a record"
|
410
|
+
setup do
|
411
|
+
@config_class.class_eval do
|
412
|
+
define_method(:ar_association_for) do |record, name|
|
413
|
+
if (reflection = record.class.reflect_on_association(name))
|
414
|
+
record.association(reflection.name)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
define_method(:build_factory_for_record_class) do |record_class|
|
418
|
+
MR::Factory::RecordFactory.new(record_class)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
@record_class = FakeTwoRecord
|
423
|
+
@record = @record_class.new
|
424
|
+
@config = @config_class.new(@record_class)
|
425
|
+
@object_builder = @object_builder_class.new(@record, @config)
|
426
|
+
end
|
427
|
+
subject{ @object_builder }
|
428
|
+
|
429
|
+
should "know how to set an association on its record" do
|
430
|
+
@record.fake_one = FakeOneRecord.new
|
431
|
+
|
432
|
+
value = [FakeOneRecord.new, nil].sample
|
433
|
+
subject.set(:fake_one, value)
|
434
|
+
|
435
|
+
assert_equal value, @record.fake_one
|
436
|
+
|
437
|
+
@record.fake_poly = FakeOneRecord.new
|
438
|
+
|
439
|
+
value = [FakeOneRecord.new, nil].sample
|
440
|
+
subject.set(:fake_poly, value)
|
441
|
+
|
442
|
+
assert_equal value, @record.fake_poly
|
443
|
+
end
|
444
|
+
|
445
|
+
should "know how to set an association when given a hash" do
|
446
|
+
associated_record_class = FakeOneRecord
|
447
|
+
association_name = Factory.boolean ? :fake_one : :fake_poly
|
448
|
+
associated_factory = MR::Factory::RecordFactory.new(associated_record_class)
|
449
|
+
if Factory.boolean
|
450
|
+
@config.add_association_factory(association_name, associated_factory)
|
451
|
+
else
|
452
|
+
@config.default_factories[associated_record_class] = associated_factory
|
453
|
+
end
|
454
|
+
|
455
|
+
apply_hash_called_with = nil
|
456
|
+
Assert.stub(@object_builder_class, :apply_hash) do |*args|
|
457
|
+
apply_hash_called_with = args
|
458
|
+
Assert.stub_send(@object_builder_class, :apply_hash, *args)
|
459
|
+
end
|
460
|
+
|
461
|
+
# when the association is already set
|
462
|
+
associated_record = associated_factory.record
|
463
|
+
@record.send("#{association_name}=", associated_record)
|
464
|
+
|
465
|
+
association_args = { :name => Factory.string }
|
466
|
+
subject.set(association_name, association_args)
|
467
|
+
|
468
|
+
assert_equal associated_record, @record.send(association_name)
|
469
|
+
assert_equal association_args[:name], associated_record.name
|
470
|
+
|
471
|
+
exp = [associated_record, associated_factory.config, association_args]
|
472
|
+
assert_equal exp, apply_hash_called_with
|
473
|
+
|
474
|
+
# when the association isn't already set
|
475
|
+
@record.send("#{association_name}=", nil)
|
476
|
+
if association_name == :fake_poly
|
477
|
+
# set the fake poly type attribute so it can find a factory for it
|
478
|
+
@record.fake_poly_type = associated_record_class.to_s
|
479
|
+
end
|
480
|
+
|
481
|
+
associated_record = associated_factory.record
|
482
|
+
Assert.stub(associated_factory, :instance){ associated_record }
|
483
|
+
|
484
|
+
association_args = { :name => Factory.string }
|
485
|
+
subject.set(association_name, association_args)
|
486
|
+
|
487
|
+
assert_equal associated_record, @record.send(association_name)
|
488
|
+
assert_equal association_args[:name], associated_record.name
|
489
|
+
|
490
|
+
exp = [associated_record, associated_factory.config, association_args]
|
491
|
+
assert_equal exp, apply_hash_called_with
|
492
|
+
end
|
493
|
+
|
494
|
+
should "raise a record class error if it can't build an association" do
|
495
|
+
assert_raises(MR::Factory::NoRecordClassError) do
|
496
|
+
subject.set(:fake_poly, {})
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
end
|
501
|
+
|
502
|
+
class ModelObjectBuilderInitTests < WithAssociationsConfigObjectBuilderTests
|
503
|
+
desc "when init with a model"
|
504
|
+
setup do
|
505
|
+
@config_class.class_eval do
|
506
|
+
define_method(:ar_association_for) do |model, name|
|
507
|
+
if (reflection = model.record_class.reflect_on_association(name))
|
508
|
+
model.record.association(reflection.name)
|
509
|
+
end
|
510
|
+
end
|
511
|
+
define_method(:build_factory_for_record_class) do |record_class|
|
512
|
+
MR::Factory::ModelFactory.new(record_class.model_class, record_class)
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
@model_class = FakeTwoModel
|
517
|
+
@model = @model_class.new
|
518
|
+
@config = @config_class.new(@model_class.record_class)
|
519
|
+
@object_builder = @object_builder_class.new(@model, @config)
|
520
|
+
end
|
521
|
+
subject{ @object_builder }
|
522
|
+
|
523
|
+
should "know how to set an association on its model" do
|
524
|
+
@model.fake_one = FakeOneModel.new
|
525
|
+
|
526
|
+
value = [FakeOneModel.new, nil].sample
|
527
|
+
subject.set(:fake_one, value)
|
528
|
+
|
529
|
+
assert_equal value, @model.fake_one
|
530
|
+
|
531
|
+
@model.fake_poly = FakeOneModel.new
|
532
|
+
|
533
|
+
value = [FakeOneModel.new, nil].sample
|
534
|
+
subject.set(:fake_poly, value)
|
535
|
+
|
536
|
+
assert_equal value, @model.fake_poly
|
537
|
+
end
|
538
|
+
|
539
|
+
should "know how to set an association when given a hash" do
|
540
|
+
associated_model_class = FakeOneModel
|
541
|
+
association_name = Factory.boolean ? :fake_one : :fake_poly
|
542
|
+
associated_factory = MR::Factory::ModelFactory.new(
|
543
|
+
associated_model_class,
|
544
|
+
associated_model_class.record_class
|
545
|
+
)
|
546
|
+
if Factory.boolean
|
547
|
+
@config.add_association_factory(association_name, associated_factory)
|
548
|
+
else
|
549
|
+
record_class = associated_model_class.record_class
|
550
|
+
@config.default_factories[record_class] = associated_factory
|
551
|
+
end
|
552
|
+
|
553
|
+
apply_hash_called_with = nil
|
554
|
+
Assert.stub(@object_builder_class, :apply_hash) do |*args|
|
555
|
+
apply_hash_called_with = args
|
556
|
+
Assert.stub_send(@object_builder_class, :apply_hash, *args)
|
557
|
+
end
|
558
|
+
|
559
|
+
# when the association is already set
|
560
|
+
associated_model = associated_factory.model
|
561
|
+
@model.send("#{association_name}=", associated_model)
|
562
|
+
|
563
|
+
association_args = { :name => Factory.string }
|
564
|
+
subject.set(association_name, association_args)
|
565
|
+
|
566
|
+
assert_equal associated_model, @model.send(association_name)
|
567
|
+
assert_equal association_args[:name], associated_model.name
|
568
|
+
|
569
|
+
exp = [associated_model, associated_factory.config, association_args]
|
570
|
+
assert_equal exp, apply_hash_called_with
|
571
|
+
|
572
|
+
# when the association isn't already set
|
573
|
+
@model.send("#{association_name}=", nil)
|
574
|
+
if association_name == :fake_poly
|
575
|
+
# set the fake poly type attribute so it can find a factory for it
|
576
|
+
@model.fake_poly_type = associated_model_class.record_class.to_s
|
577
|
+
end
|
578
|
+
|
579
|
+
associated_model = associated_factory.model
|
580
|
+
Assert.stub(associated_factory, :instance){ associated_model }
|
581
|
+
|
582
|
+
association_args = { :name => Factory.string }
|
583
|
+
subject.set(association_name, association_args)
|
584
|
+
|
585
|
+
assert_equal associated_model, @model.send(association_name)
|
586
|
+
assert_equal association_args[:name], associated_model.name
|
587
|
+
|
588
|
+
exp = [associated_model, associated_factory.config, association_args]
|
589
|
+
assert_equal exp, apply_hash_called_with
|
590
|
+
end
|
591
|
+
|
592
|
+
should "raise a record class error if it can't build an association" do
|
593
|
+
assert_raises(MR::Factory::NoRecordClassError) do
|
594
|
+
subject.set(:fake_poly, {})
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
end
|
599
|
+
|
600
|
+
class FakeOneRecord
|
601
|
+
include MR::FakeRecord
|
602
|
+
|
603
|
+
attribute :name, :string
|
604
|
+
end
|
605
|
+
|
606
|
+
class FakeTwoRecord
|
607
|
+
include MR::FakeRecord
|
608
|
+
|
609
|
+
attribute :name, :string
|
610
|
+
attribute :fake_poly_type, :string
|
611
|
+
attribute :fake_poly_id, :integer
|
612
|
+
attribute :fake_one_id, :integer
|
613
|
+
|
614
|
+
belongs_to :fake_poly, :polymorphic => true
|
615
|
+
belongs_to :fake_one, :class_name => FakeOneRecord.to_s
|
616
|
+
end
|
617
|
+
|
618
|
+
class FakeThreeRecord
|
619
|
+
include MR::FakeRecord
|
620
|
+
|
621
|
+
attribute :fake_one_id, :integer
|
622
|
+
attribute :fake_two_id, :integer
|
623
|
+
|
624
|
+
belongs_to :fake_one, :class_name => FakeOneRecord.to_s
|
625
|
+
belongs_to :fake_two, :class_name => FakeTwoRecord.to_s
|
626
|
+
end
|
627
|
+
|
628
|
+
class FakeOneModel
|
629
|
+
include MR::Model
|
630
|
+
record_class FakeOneRecord
|
631
|
+
|
632
|
+
field_accessor :name
|
633
|
+
end
|
634
|
+
|
635
|
+
class FakeTwoModel
|
636
|
+
include MR::Model
|
637
|
+
record_class FakeTwoRecord
|
638
|
+
|
639
|
+
field_accessor :name, :fake_poly_type, :fake_poly_id, :fake_one_id
|
640
|
+
|
641
|
+
polymorphic_belongs_to :fake_poly
|
642
|
+
belongs_to :fake_one
|
643
|
+
end
|
644
|
+
|
645
|
+
class TestReadModel
|
646
|
+
include MR::ReadModel
|
647
|
+
|
648
|
+
field :name, :string
|
649
|
+
end
|
650
|
+
|
651
|
+
end
|