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,346 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/model/associations'
|
3
|
+
|
4
|
+
require 'much-plugin'
|
5
|
+
require 'mr/fake_record'
|
6
|
+
require 'mr/model'
|
7
|
+
|
8
|
+
module MR::Model::Associations
|
9
|
+
|
10
|
+
class UnitTests < Assert::Context
|
11
|
+
desc "MR::Model::Associations"
|
12
|
+
setup do
|
13
|
+
@model_class = Class.new do
|
14
|
+
include MR::Model::Associations
|
15
|
+
record_class FakeRecordWithAssociations
|
16
|
+
def initialize(record); set_record record; end
|
17
|
+
end
|
18
|
+
@record = FakeRecordWithAssociations.new
|
19
|
+
end
|
20
|
+
subject{ @model_class }
|
21
|
+
|
22
|
+
should have_imeths :associations
|
23
|
+
should have_imeths :belongs_to, :polymorphic_belongs_to
|
24
|
+
should have_imeths :has_one, :has_many
|
25
|
+
|
26
|
+
should "use much-plugin" do
|
27
|
+
assert_includes MuchPlugin, MR::Model::Associations
|
28
|
+
end
|
29
|
+
|
30
|
+
should "include Model::Configuration mixin" do
|
31
|
+
assert_includes MR::Model::Configuration, subject.included_modules
|
32
|
+
end
|
33
|
+
|
34
|
+
should "return an instance of a AssociationSet using `associations`" do
|
35
|
+
associations = subject.associations
|
36
|
+
assert_instance_of MR::Model::AssociationSet, associations
|
37
|
+
assert_same associations, subject.associations
|
38
|
+
end
|
39
|
+
|
40
|
+
should "add accessors methods for a belongs to association using `belongs_to`" do
|
41
|
+
subject.belongs_to :area
|
42
|
+
model = subject.new(@record)
|
43
|
+
new_record = FakeTestRecord.new
|
44
|
+
new_model = FakeTestModel.new(new_record)
|
45
|
+
|
46
|
+
assert_respond_to :area, model
|
47
|
+
assert_respond_to :area=, model
|
48
|
+
model.area = new_model
|
49
|
+
assert_instance_of FakeTestModel, model.area
|
50
|
+
assert_equal new_record, @record.area
|
51
|
+
end
|
52
|
+
|
53
|
+
should "add accessors methods for a polymorphic belongs to association " \
|
54
|
+
"using `polymorphic_belongs_to`" do
|
55
|
+
subject.polymorphic_belongs_to :parent
|
56
|
+
model = subject.new(@record)
|
57
|
+
new_record = FakeTestRecord.new
|
58
|
+
new_model = FakeTestModel.new(new_record)
|
59
|
+
|
60
|
+
assert_respond_to :parent, model
|
61
|
+
assert_respond_to :parent=, model
|
62
|
+
model.parent = new_model
|
63
|
+
assert_instance_of FakeTestModel, model.parent
|
64
|
+
assert_equal new_record, @record.parent
|
65
|
+
end
|
66
|
+
|
67
|
+
should "add accessors methods for a has one association using `has_one`" do
|
68
|
+
subject.has_one :image
|
69
|
+
model = subject.new(@record)
|
70
|
+
new_record = FakeTestRecord.new
|
71
|
+
new_model = FakeTestModel.new(new_record)
|
72
|
+
|
73
|
+
assert_respond_to :image, model
|
74
|
+
assert_respond_to :image=, model
|
75
|
+
model.image = new_model
|
76
|
+
assert_instance_of FakeTestModel, model.image
|
77
|
+
assert_equal new_record, @record.image
|
78
|
+
end
|
79
|
+
|
80
|
+
should "add accessors methods for a has many association using `has_many`" do
|
81
|
+
subject.has_many :comments
|
82
|
+
model = subject.new(@record)
|
83
|
+
first_record = FakeTestRecord.new
|
84
|
+
first_model = FakeTestModel.new(first_record)
|
85
|
+
second_record = FakeTestRecord.new
|
86
|
+
second_model = FakeTestModel.new(second_record)
|
87
|
+
|
88
|
+
assert_respond_to :comments, model
|
89
|
+
assert_respond_to :comments=, model
|
90
|
+
model.comments = [ first_model, second_model ]
|
91
|
+
assert_instance_of Array, model.comments
|
92
|
+
assert_includes first_record, @record.comments
|
93
|
+
assert_includes second_record, @record.comments
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
class InstanceTests < UnitTests
|
99
|
+
desc "for a model instance"
|
100
|
+
setup do
|
101
|
+
@model_class.class_eval do
|
102
|
+
belongs_to :area
|
103
|
+
polymorphic_belongs_to :parent
|
104
|
+
has_one :image
|
105
|
+
has_many :comments
|
106
|
+
end
|
107
|
+
@model = @model_class.new(@record)
|
108
|
+
end
|
109
|
+
subject{ @model }
|
110
|
+
|
111
|
+
should "raise an ArgumentError if writing non MR::Model values to associations" do
|
112
|
+
assert_raises(ArgumentError){ subject.area = 'test' }
|
113
|
+
assert_raises(ArgumentError){ subject.parent = 'test' }
|
114
|
+
assert_raises(ArgumentError){ subject.image = 'test' }
|
115
|
+
assert_raises(ArgumentError){ subject.comments = [ 'test' ] }
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
class AssociationSetTests < UnitTests
|
121
|
+
desc "AssociationSet"
|
122
|
+
setup do
|
123
|
+
@association_set = MR::Model::AssociationSet.new
|
124
|
+
end
|
125
|
+
subject{ @association_set }
|
126
|
+
|
127
|
+
should have_readers :belongs_to, :polymorphic_belongs_to
|
128
|
+
should have_readers :has_one, :has_many
|
129
|
+
should have_imeths :add_belongs_to, :add_polymorphic_belongs_to
|
130
|
+
should have_imeths :add_has_one, :add_has_many
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
class AssociationTests < UnitTests
|
135
|
+
desc "Association"
|
136
|
+
setup do
|
137
|
+
@association = MR::Model::Association.new(:test)
|
138
|
+
end
|
139
|
+
subject{ @association }
|
140
|
+
|
141
|
+
should have_readers :name
|
142
|
+
should have_readers :reader_method_name, :writer_method_name
|
143
|
+
|
144
|
+
should "know it's name and method names" do
|
145
|
+
assert_equal 'test', subject.name
|
146
|
+
assert_equal 'test', subject.reader_method_name
|
147
|
+
assert_equal 'test=', subject.writer_method_name
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
class OneToOneAssociationTests < UnitTests
|
153
|
+
desc "OneToOneAssociation"
|
154
|
+
setup do
|
155
|
+
@test_record = FakeTestRecord.new.tap{ |r| r.save! }
|
156
|
+
@test_model = FakeTestModel.new(@test_record)
|
157
|
+
@other_record = FakeTestRecord.new.tap{ |r| r.save! }
|
158
|
+
@other_model = FakeTestModel.new(@other_record)
|
159
|
+
|
160
|
+
@association = MR::Model::OneToOneAssociation.new(:area)
|
161
|
+
end
|
162
|
+
subject{ @association }
|
163
|
+
|
164
|
+
should have_imeths :read, :write
|
165
|
+
|
166
|
+
should "be a kind of Association" do
|
167
|
+
assert_kind_of MR::Model::Association, subject
|
168
|
+
end
|
169
|
+
|
170
|
+
should "allow reading the record's association using `read`" do
|
171
|
+
@test_record.area = @other_record
|
172
|
+
assert_equal @other_model, subject.read(@test_record)
|
173
|
+
end
|
174
|
+
|
175
|
+
should "allow reading `nil` values for the record's association using `read`" do
|
176
|
+
@test_record.area = nil
|
177
|
+
assert_nil subject.read(@test_record)
|
178
|
+
end
|
179
|
+
|
180
|
+
should "allow writing the record's association using `write`" do
|
181
|
+
record = @other_record
|
182
|
+
yielded = nil
|
183
|
+
result = subject.write(@other_model, @test_model, @test_record) do |object|
|
184
|
+
yielded = object; record
|
185
|
+
end
|
186
|
+
|
187
|
+
assert_equal @other_model, yielded
|
188
|
+
assert_equal @other_record, @test_record.area
|
189
|
+
assert_equal @test_model.send(subject.name), result
|
190
|
+
end
|
191
|
+
|
192
|
+
should "allow writing `nil` values to the record's association using `write`" do
|
193
|
+
subject.write(nil, @test_model, @test_record){ raise 'test' }
|
194
|
+
assert_nil @test_record.area
|
195
|
+
end
|
196
|
+
|
197
|
+
should "raise a bad association value error when writing a non MR::Model" do
|
198
|
+
assert_raises(MR::Model::BadAssociationValueError) do
|
199
|
+
subject.write('test', @test_model, @test_record){ }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
class OneToManyAssociationTests < UnitTests
|
206
|
+
desc "OneToManyAssociation"
|
207
|
+
setup do
|
208
|
+
@test_record = FakeTestRecord.new.tap{ |r| r.save! }
|
209
|
+
@test_model = FakeTestModel.new(@test_record)
|
210
|
+
@first_record = FakeTestRecord.new.tap{ |r| r.save! }
|
211
|
+
@first_model = FakeTestModel.new(@first_record)
|
212
|
+
@second_record = FakeTestRecord.new.tap{ |r| r.save! }
|
213
|
+
@second_model = FakeTestModel.new(@second_record)
|
214
|
+
|
215
|
+
@association = MR::Model::OneToManyAssociation.new(:comments)
|
216
|
+
end
|
217
|
+
subject{ @association }
|
218
|
+
|
219
|
+
should have_imeths :read, :write
|
220
|
+
|
221
|
+
should "be a kind of Association" do
|
222
|
+
assert_kind_of MR::Model::Association, subject
|
223
|
+
end
|
224
|
+
|
225
|
+
should "allow reading the record's association using `read`" do
|
226
|
+
@test_record.comments = [ @first_record ]
|
227
|
+
expected = [ @first_model ]
|
228
|
+
assert_equal expected, subject.read(@test_record)
|
229
|
+
end
|
230
|
+
|
231
|
+
should "allow reading `nil` values for the record's association using `read`" do
|
232
|
+
@test_record.comments = []
|
233
|
+
assert_equal [], subject.read(@test_record)
|
234
|
+
end
|
235
|
+
|
236
|
+
should "allow writing the record's association using `write`" do
|
237
|
+
models = [ @first_model, @second_model ]
|
238
|
+
yielded = []
|
239
|
+
results = subject.write(models, @test_model, @test_record) do |object|
|
240
|
+
yielded << object; object.record
|
241
|
+
end
|
242
|
+
|
243
|
+
assert_equal models, yielded
|
244
|
+
records = [ @first_record, @second_record ]
|
245
|
+
assert_equal records, @test_record.comments
|
246
|
+
assert_equal @test_model.send(subject.name), results
|
247
|
+
end
|
248
|
+
|
249
|
+
should "allow writing a single value to the record's association using `write`" do
|
250
|
+
subject.write(@second_model, @test_model, @test_record) do |object|
|
251
|
+
object.record
|
252
|
+
end
|
253
|
+
assert_equal [ @second_record ], @test_record.comments
|
254
|
+
end
|
255
|
+
|
256
|
+
should "allow writing `nil` values to the record's association using `write`" do
|
257
|
+
subject.write(nil, @test_model, @test_record){ raise 'test' }
|
258
|
+
assert_equal [], @test_record.comments
|
259
|
+
end
|
260
|
+
|
261
|
+
should "raise a bad association value error when writing a non MR::Model" do
|
262
|
+
assert_raises(MR::Model::BadAssociationValueError) do
|
263
|
+
subject.write('test', @test_model, @test_record){ }
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
class BelongsToAssociationTests < UnitTests
|
270
|
+
desc "BelongsToAssociation"
|
271
|
+
setup do
|
272
|
+
@association = MR::Model::BelongsToAssociation.new(:test)
|
273
|
+
end
|
274
|
+
subject{ @association }
|
275
|
+
|
276
|
+
should "be a kind of OneToOneAssociation" do
|
277
|
+
assert_kind_of MR::Model::OneToOneAssociation, subject
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
class HasOneAssociationTests < UnitTests
|
283
|
+
desc "HasOneAssociation"
|
284
|
+
setup do
|
285
|
+
@association = MR::Model::HasOneAssociation.new(:test)
|
286
|
+
end
|
287
|
+
subject{ @association }
|
288
|
+
|
289
|
+
should "be a kind of OneToOneAssociation" do
|
290
|
+
assert_kind_of MR::Model::OneToOneAssociation, subject
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
class HasManyAssociationTests < UnitTests
|
296
|
+
desc "HasManyAssociation"
|
297
|
+
setup do
|
298
|
+
@association = MR::Model::HasManyAssociation.new(:test)
|
299
|
+
end
|
300
|
+
subject{ @association }
|
301
|
+
|
302
|
+
should "be a kind of OneToManyAssociation" do
|
303
|
+
assert_kind_of MR::Model::OneToManyAssociation, subject
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
class PolymorphicBelongsToAssociationTests < UnitTests
|
309
|
+
desc "PolymorphicBelongsToAssociation"
|
310
|
+
setup do
|
311
|
+
@association = MR::Model::PolymorphicBelongsToAssociation.new(:test)
|
312
|
+
end
|
313
|
+
subject{ @association }
|
314
|
+
|
315
|
+
should "be a kind of BelongsToAssociation" do
|
316
|
+
assert_kind_of MR::Model::BelongsToAssociation, subject
|
317
|
+
end
|
318
|
+
|
319
|
+
end
|
320
|
+
|
321
|
+
class FakeRecordWithAssociations
|
322
|
+
include MR::FakeRecord
|
323
|
+
attribute :area_id, :integer
|
324
|
+
attribute :parent_type, :string
|
325
|
+
attribute :parent_id, :integer
|
326
|
+
belongs_to :area, :class_name => 'MR::Model::Associations::FakeRecordWithAssociations'
|
327
|
+
belongs_to :parent, :polymorphic => true
|
328
|
+
has_one :image, :class_name => 'MR::Model::Associations::FakeRecordWithAssociations'
|
329
|
+
has_many :comments, :class_name => 'MR::Model::Associations::FakeRecordWithAssociations'
|
330
|
+
end
|
331
|
+
|
332
|
+
class FakeTestRecord
|
333
|
+
include MR::FakeRecord
|
334
|
+
attribute :area_id, :integer
|
335
|
+
belongs_to :area, :class_name => 'MR::Model::Associations::FakeTestRecord'
|
336
|
+
has_many :comments, :class_name => 'MR::Model::Associations::FakeTestRecord'
|
337
|
+
end
|
338
|
+
|
339
|
+
class FakeTestModel
|
340
|
+
include MR::Model
|
341
|
+
record_class FakeTestRecord
|
342
|
+
belongs_to :area
|
343
|
+
has_many :comments
|
344
|
+
end
|
345
|
+
|
346
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/model/configuration'
|
3
|
+
|
4
|
+
require 'much-plugin'
|
5
|
+
require 'mr/fake_record'
|
6
|
+
|
7
|
+
module MR::Model::Configuration
|
8
|
+
|
9
|
+
class UnitTests < Assert::Context
|
10
|
+
desc "MR::Model::Configuration"
|
11
|
+
setup do
|
12
|
+
@model_class = Class.new do
|
13
|
+
include MR::Model::Configuration
|
14
|
+
end
|
15
|
+
end
|
16
|
+
subject{ @model_class }
|
17
|
+
|
18
|
+
should have_imeths :record_class
|
19
|
+
|
20
|
+
should "use much-plugin" do
|
21
|
+
assert_includes MuchPlugin, MR::Model::Configuration
|
22
|
+
end
|
23
|
+
|
24
|
+
should "allow reading and writing it's record class with `record_class`" do
|
25
|
+
subject.record_class FakeTestRecord
|
26
|
+
assert_equal FakeTestRecord, subject.record_class
|
27
|
+
end
|
28
|
+
|
29
|
+
should "raise a no record class error if a record class hasn't been set" do
|
30
|
+
assert_raises(MR::Model::NoRecordClassError){ subject.record_class }
|
31
|
+
end
|
32
|
+
|
33
|
+
should "raise an ArgumentError when a non MR::Record `record_class` is written" do
|
34
|
+
assert_raises(ArgumentError){ subject.record_class('fake-class') }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class InstanceTests < UnitTests
|
40
|
+
|
41
|
+
# These private methods are tested because they are an interace to the other
|
42
|
+
# mixins.
|
43
|
+
|
44
|
+
desc "for a model instance"
|
45
|
+
setup do
|
46
|
+
@model_class.class_eval do
|
47
|
+
record_class FakeTestRecord
|
48
|
+
|
49
|
+
def read_record
|
50
|
+
record
|
51
|
+
end
|
52
|
+
|
53
|
+
def write_record(record)
|
54
|
+
set_record(record)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
@record = FakeTestRecord.new
|
58
|
+
@model = @model_class.new
|
59
|
+
end
|
60
|
+
subject{ @model }
|
61
|
+
|
62
|
+
should have_imeths :record_class
|
63
|
+
|
64
|
+
should "allow reading the model class' record class using `record_class`" do
|
65
|
+
assert_equal @model_class.record_class, subject.record_class
|
66
|
+
end
|
67
|
+
|
68
|
+
should "allow reading the `record` through the protected method" do
|
69
|
+
subject.write_record(@record)
|
70
|
+
assert_equal @record, subject.read_record
|
71
|
+
end
|
72
|
+
|
73
|
+
should "set the record's model when `set_record` is called" do
|
74
|
+
subject.write_record(@record)
|
75
|
+
assert_equal @model, @record.model
|
76
|
+
end
|
77
|
+
|
78
|
+
should "raise a no record error if a record hasn't been set" do
|
79
|
+
assert_raises(MR::Model::NoRecordError){ subject.read_record }
|
80
|
+
end
|
81
|
+
|
82
|
+
should "raise an invalid record error when setting record without an MR::Record" do
|
83
|
+
assert_raises(MR::Model::InvalidRecordError){ subject.write_record('fake') }
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
class FakeTestRecord
|
89
|
+
include MR::FakeRecord
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,278 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/model/fields'
|
3
|
+
|
4
|
+
require 'much-plugin'
|
5
|
+
require 'mr/fake_record'
|
6
|
+
|
7
|
+
module MR::Model::Fields
|
8
|
+
|
9
|
+
class UnitTests < Assert::Context
|
10
|
+
desc "MR::Model::Fields"
|
11
|
+
setup do
|
12
|
+
@model_class = Class.new do
|
13
|
+
include MR::Model::Fields
|
14
|
+
def initialize(record); set_record record; end
|
15
|
+
end
|
16
|
+
@record = FakeTestRecord.new
|
17
|
+
end
|
18
|
+
subject{ @model_class }
|
19
|
+
|
20
|
+
should have_imeths :fields, :field_reader, :field_writer, :field_accessor
|
21
|
+
should have_imeths :field_names
|
22
|
+
|
23
|
+
should "use much-plugin" do
|
24
|
+
assert_includes MuchPlugin, MR::Model::Fields
|
25
|
+
end
|
26
|
+
|
27
|
+
should "include Model::Configuration mixin" do
|
28
|
+
assert_includes MR::Model::Configuration, subject
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return an instance of a FieldSet using `fields`" do
|
32
|
+
fields = subject.fields
|
33
|
+
assert_instance_of MR::Model::FieldSet, fields
|
34
|
+
assert_same fields, subject.fields
|
35
|
+
end
|
36
|
+
|
37
|
+
should "add reader methods for a field using `field_reader`" do
|
38
|
+
subject.field_reader :name
|
39
|
+
@record.name = 'test'
|
40
|
+
model = subject.new(@record)
|
41
|
+
|
42
|
+
assert_respond_to :name, model
|
43
|
+
assert_respond_to :name_was, model
|
44
|
+
assert_respond_to :name_changed?, model
|
45
|
+
assert_equal @record.name, model.name
|
46
|
+
assert_equal @record.name_was, model.name_was
|
47
|
+
assert_equal @record.name_changed?, model.name_changed?
|
48
|
+
end
|
49
|
+
|
50
|
+
should "add writer methods for a field using `field_writer`" do
|
51
|
+
subject.field_writer :name
|
52
|
+
model = subject.new(@record)
|
53
|
+
|
54
|
+
assert_respond_to :name=, model
|
55
|
+
model.name = 'test'
|
56
|
+
assert_equal 'test', @record.name
|
57
|
+
end
|
58
|
+
|
59
|
+
should "add accessor methods for a field using `field_accessor`" do
|
60
|
+
subject.field_accessor :name
|
61
|
+
model = subject.new(@record)
|
62
|
+
|
63
|
+
assert_respond_to :name, model
|
64
|
+
assert_respond_to :name_changed?, model
|
65
|
+
assert_respond_to :name=, model
|
66
|
+
model.name = 'test'
|
67
|
+
assert_equal 'test', @record.name
|
68
|
+
assert_equal @record.name, model.name
|
69
|
+
assert_equal @record.name_changed?, model.name_changed?
|
70
|
+
end
|
71
|
+
|
72
|
+
should "know its field names" do
|
73
|
+
assert_equal [], subject.field_names
|
74
|
+
|
75
|
+
subject.field_reader :field1
|
76
|
+
subject.field_writer :field2
|
77
|
+
subject.field_accessor :field3
|
78
|
+
|
79
|
+
result = subject.field_names
|
80
|
+
assert_equal subject.fields.names, result
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class InstanceTests < UnitTests
|
86
|
+
desc "for a model instance"
|
87
|
+
setup do
|
88
|
+
@model_class.class_eval do
|
89
|
+
field_accessor :name, :active, :description
|
90
|
+
end
|
91
|
+
@model = @model_class.new(@record)
|
92
|
+
end
|
93
|
+
subject{ @model }
|
94
|
+
|
95
|
+
should have_imeths :fields, :fields=
|
96
|
+
|
97
|
+
should "allow reading all the fields using `fields`" do
|
98
|
+
subject.name = 'test'
|
99
|
+
subject.active = true
|
100
|
+
subject.description = 'desc'
|
101
|
+
|
102
|
+
expected = {
|
103
|
+
'name' => 'test',
|
104
|
+
'active' => true,
|
105
|
+
'description' => 'desc'
|
106
|
+
}
|
107
|
+
assert_equal expected, subject.fields
|
108
|
+
end
|
109
|
+
|
110
|
+
should "allow writing multiple fields using `fields=`" do
|
111
|
+
subject.fields = {
|
112
|
+
'name' => 'test',
|
113
|
+
'active' => true,
|
114
|
+
'description' => 'desc'
|
115
|
+
}
|
116
|
+
assert_equal 'test', subject.name
|
117
|
+
assert_equal true, subject.active
|
118
|
+
assert_equal 'desc', subject.description
|
119
|
+
end
|
120
|
+
|
121
|
+
should "raise an ArgumentError when a non-Hash is passed to `fields=`" do
|
122
|
+
assert_raises(ArgumentError){ subject.fields = 'test' }
|
123
|
+
end
|
124
|
+
|
125
|
+
should "raise a no field error when writing a bad field using `fields=`" do
|
126
|
+
assert_raises(MR::Model::NoFieldError) do
|
127
|
+
subject.fields = { :not_valid => 'test' }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
class FieldSetTests < UnitTests
|
134
|
+
desc "FieldSet"
|
135
|
+
setup do
|
136
|
+
@fields_set = MR::Model::FieldSet.new
|
137
|
+
end
|
138
|
+
subject{ @fields_set }
|
139
|
+
|
140
|
+
should have_imeths :names, :find, :get
|
141
|
+
should have_imeths :read_all, :batch_write
|
142
|
+
should have_imeths :add_reader, :add_writer
|
143
|
+
|
144
|
+
should "know its field names" do
|
145
|
+
assert_equal [], subject.names
|
146
|
+
|
147
|
+
subject.add_reader(:field1, @model_class)
|
148
|
+
subject.add_writer(:field2, @model_class)
|
149
|
+
|
150
|
+
assert_equal 2, subject.names.size
|
151
|
+
assert_includes 'field1', subject.names
|
152
|
+
assert_includes 'field2', subject.names
|
153
|
+
end
|
154
|
+
|
155
|
+
should "return an existing field or raise a no field error using `find`" do
|
156
|
+
subject.get('name')
|
157
|
+
field = subject.find('name')
|
158
|
+
assert_instance_of MR::Model::Field, field
|
159
|
+
assert_equal 'name', field.name
|
160
|
+
|
161
|
+
assert_raises(MR::Model::NoFieldError){ subject.find('not_valid') }
|
162
|
+
end
|
163
|
+
|
164
|
+
should "return an existing field or build a new field using `get`" do
|
165
|
+
field = subject.get('name')
|
166
|
+
assert_instance_of MR::Model::Field, field
|
167
|
+
assert_equal 'name', field.name
|
168
|
+
assert_same field, subject.get('name')
|
169
|
+
end
|
170
|
+
|
171
|
+
should "return a hash of field names and values using `read_all`" do
|
172
|
+
assert_equal({}, subject.read_all(@record))
|
173
|
+
subject.get('name')
|
174
|
+
@record.name = 'test'
|
175
|
+
assert_equal({ 'name' => 'test' }, subject.read_all(@record))
|
176
|
+
end
|
177
|
+
|
178
|
+
should "set multiple field values using `batch_write`" do
|
179
|
+
subject.get('name')
|
180
|
+
subject.get('active')
|
181
|
+
values = { :name => 'test', :active => true }
|
182
|
+
subject.batch_write(values, @record)
|
183
|
+
|
184
|
+
assert_equal 'test', @record.name
|
185
|
+
assert_equal true, @record.active
|
186
|
+
end
|
187
|
+
|
188
|
+
should "add a field and define reader methods for it using `add_reader`" do
|
189
|
+
subject.add_reader('name', @model_class)
|
190
|
+
|
191
|
+
assert_instance_of MR::Model::Field, subject.find('name')
|
192
|
+
model = @model_class.new(@record)
|
193
|
+
assert_respond_to :name, model
|
194
|
+
assert_respond_to :name_changed?, model
|
195
|
+
end
|
196
|
+
|
197
|
+
should "add a field and define writer methods for it using `add_writer`" do
|
198
|
+
subject.add_writer('name', @model_class)
|
199
|
+
|
200
|
+
assert_instance_of MR::Model::Field, subject.find('name')
|
201
|
+
model = @model_class.new(@record)
|
202
|
+
assert_respond_to :name=, model
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
class FieldTests < UnitTests
|
208
|
+
desc "Field"
|
209
|
+
setup do
|
210
|
+
@field = MR::Model::Field.new('name')
|
211
|
+
end
|
212
|
+
subject{ @field }
|
213
|
+
|
214
|
+
should have_readers :name
|
215
|
+
should have_readers :reader_method_name, :writer_method_name
|
216
|
+
should have_readers :was_method_name, :changed_method_name
|
217
|
+
|
218
|
+
should have_imeths :read, :write, :was, :changed?
|
219
|
+
should have_imeths :define_reader_on, :define_writer_on
|
220
|
+
|
221
|
+
should "know it's name and method names" do
|
222
|
+
assert_equal 'name', subject.name
|
223
|
+
assert_equal 'name', subject.reader_method_name
|
224
|
+
assert_equal 'name_was', subject.was_method_name
|
225
|
+
assert_equal 'name_changed?', subject.changed_method_name
|
226
|
+
assert_equal 'name=', subject.writer_method_name
|
227
|
+
end
|
228
|
+
|
229
|
+
should "read a record's attribute using `read`" do
|
230
|
+
@record.name = 'test'
|
231
|
+
assert_equal 'test', subject.read(@record)
|
232
|
+
end
|
233
|
+
|
234
|
+
should "write a record's attribute using `write`" do
|
235
|
+
subject.write('test', @record)
|
236
|
+
assert_equal 'test', @record.name
|
237
|
+
end
|
238
|
+
|
239
|
+
should "read a record attribute's prevous value using `was`" do
|
240
|
+
assert_nil subject.was(@record)
|
241
|
+
@record.name = 'Test'
|
242
|
+
assert_nil subject.was(@record)
|
243
|
+
@record.save!
|
244
|
+
assert_equal 'Test', subject.was(@record)
|
245
|
+
@record.name = 'New test'
|
246
|
+
assert_equal 'Test', subject.was(@record)
|
247
|
+
end
|
248
|
+
|
249
|
+
should "return if a record's attribute has changed using `changed`" do
|
250
|
+
assert_equal false, subject.changed?(@record)
|
251
|
+
subject.write('test', @record)
|
252
|
+
assert_equal true, subject.changed?(@record)
|
253
|
+
end
|
254
|
+
|
255
|
+
should "define reader methods using `define_reader_on`" do
|
256
|
+
subject.define_reader_on(@model_class)
|
257
|
+
model = @model_class.new(@record)
|
258
|
+
assert_respond_to :name, model
|
259
|
+
assert_respond_to :name_was, model
|
260
|
+
assert_respond_to :name_changed?, model
|
261
|
+
end
|
262
|
+
|
263
|
+
should "define writer methods using `define_writer_on`" do
|
264
|
+
subject.define_writer_on(@model_class)
|
265
|
+
model = @model_class.new(@record)
|
266
|
+
assert_respond_to :name=, model
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
class FakeTestRecord
|
272
|
+
include MR::FakeRecord
|
273
|
+
attribute :name, :string
|
274
|
+
attribute :active, :boolean
|
275
|
+
attribute :description, :text
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|