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,213 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/factory'
|
3
|
+
|
4
|
+
require 'thread'
|
5
|
+
require 'mr/fake_record'
|
6
|
+
require 'mr/model'
|
7
|
+
require 'mr/read_model'
|
8
|
+
require 'mr/type_converter'
|
9
|
+
|
10
|
+
module MR::Factory
|
11
|
+
|
12
|
+
class UnitTests < Assert::Context
|
13
|
+
desc "MR::Factory"
|
14
|
+
setup do
|
15
|
+
@type_converter = MR::TypeConverter.new
|
16
|
+
end
|
17
|
+
subject{ MR::Factory }
|
18
|
+
|
19
|
+
should have_imeths :new
|
20
|
+
should have_imeths :primary_key, :decimal, :timestamp
|
21
|
+
should have_imeths :type_converter
|
22
|
+
|
23
|
+
should "extend `Assert::Factory`" do
|
24
|
+
assert_respond_to :integer, subject
|
25
|
+
assert_respond_to :float, subject
|
26
|
+
assert_respond_to :date, subject
|
27
|
+
assert_respond_to :datetime, subject
|
28
|
+
assert_respond_to :time, subject
|
29
|
+
assert_respond_to :string, subject
|
30
|
+
assert_respond_to :text, subject
|
31
|
+
assert_respond_to :slug, subject
|
32
|
+
assert_respond_to :hex, subject
|
33
|
+
assert_respond_to :binary, subject
|
34
|
+
assert_respond_to :file_name, subject
|
35
|
+
assert_respond_to :dir_path, subject
|
36
|
+
assert_respond_to :file_path, subject
|
37
|
+
assert_respond_to :boolean, subject
|
38
|
+
end
|
39
|
+
|
40
|
+
should "return unique integers for an identifier using `primary_key`" do
|
41
|
+
assert_equal 1, subject.primary_key('test')
|
42
|
+
assert_equal 2, subject.primary_key('test')
|
43
|
+
assert_equal 1, subject.primary_key('other')
|
44
|
+
end
|
45
|
+
|
46
|
+
should "return a random decimal using `decimal`" do
|
47
|
+
assert_kind_of BigDecimal, subject.decimal
|
48
|
+
end
|
49
|
+
|
50
|
+
should "allow passing a maximum value using `decimal`" do
|
51
|
+
decimal = subject.decimal(2)
|
52
|
+
assert decimal <= 2
|
53
|
+
assert decimal >= 0
|
54
|
+
end
|
55
|
+
|
56
|
+
should "return a random time object using `timestamp`" do
|
57
|
+
assert_kind_of Time, subject.timestamp
|
58
|
+
end
|
59
|
+
|
60
|
+
should "return an instance of MR::TypeConverter using `type_converter`" do
|
61
|
+
assert_instance_of MR::TypeConverter, subject.type_converter
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
class NewTests < UnitTests
|
67
|
+
desc "new"
|
68
|
+
setup do
|
69
|
+
@record_factory_built_with = nil
|
70
|
+
Assert.stub(MR::Factory::RecordFactory, :new) do |*args, &block|
|
71
|
+
@record_factory_built_with = args + [block]
|
72
|
+
Assert.stub_send(MR::Factory::RecordFactory, :new, *args, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
@model_factory_built_with = nil
|
76
|
+
Assert.stub(MR::Factory::ModelFactory, :new) do |*args, &block|
|
77
|
+
@model_factory_built_with = args + [block]
|
78
|
+
Assert.stub_send(MR::Factory::ModelFactory, :new, *args, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
@read_model_factory_built_with = nil
|
82
|
+
Assert.stub(MR::Factory::ReadModelFactory, :new) do |*args, &block|
|
83
|
+
@read_model_factory_built_with = args + [block]
|
84
|
+
Assert.stub_send(MR::Factory::ReadModelFactory, :new, *args, &block)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
should "build a record factory when passed a record class" do
|
89
|
+
block = proc{ Factory.string }
|
90
|
+
|
91
|
+
factory = subject.new(TestFakeRecord, &block)
|
92
|
+
assert_equal [TestFakeRecord, block], @record_factory_built_with
|
93
|
+
assert_instance_of MR::Factory::RecordFactory, factory
|
94
|
+
end
|
95
|
+
|
96
|
+
should "build a model factory when passed a model class" do
|
97
|
+
block = proc{ Factory.string }
|
98
|
+
|
99
|
+
factory = subject.new(TestFakeModel, TestFakeRecord, &block)
|
100
|
+
assert_equal [TestFakeModel, TestFakeRecord, block], @model_factory_built_with
|
101
|
+
assert_instance_of MR::Factory::ModelFactory, factory
|
102
|
+
end
|
103
|
+
|
104
|
+
should "build a read model factory when passed a read model class" do
|
105
|
+
block = proc{ Factory.string }
|
106
|
+
|
107
|
+
factory = subject.new(TestReadModel, &block)
|
108
|
+
assert_equal [TestReadModel, block], @read_model_factory_built_with
|
109
|
+
assert_instance_of MR::Factory::ReadModelFactory, factory
|
110
|
+
end
|
111
|
+
|
112
|
+
should "build a read model factory when passed a read model struct class" do
|
113
|
+
block = proc{ Factory.string }
|
114
|
+
|
115
|
+
factory = subject.new(TestReadModelStruct, &block)
|
116
|
+
assert_equal [TestReadModelStruct, block], @read_model_factory_built_with
|
117
|
+
assert_instance_of MR::Factory::ReadModelFactory, factory
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class PrimaryKeyProviderTests < UnitTests
|
123
|
+
desc "PrimaryKeyProvider"
|
124
|
+
setup do
|
125
|
+
@provider = PrimaryKeyProvider.new
|
126
|
+
@started_at = @provider.current
|
127
|
+
end
|
128
|
+
subject{ @provider }
|
129
|
+
|
130
|
+
should have_readers :mutex, :current
|
131
|
+
|
132
|
+
should "store a mutex and it's current value" do
|
133
|
+
assert_instance_of Mutex, subject.mutex
|
134
|
+
assert_instance_of Fixnum, subject.current
|
135
|
+
end
|
136
|
+
|
137
|
+
should "increated the counter and return the value using `next`" do
|
138
|
+
next_id = subject.next
|
139
|
+
assert_equal @started_at + 1, next_id
|
140
|
+
assert_equal @started_at + 1, subject.current
|
141
|
+
end
|
142
|
+
|
143
|
+
should "lock getting the next value using `next`" do
|
144
|
+
threads = [*0..2].map do |n|
|
145
|
+
Thread.new{ Thread.current['id'] = @provider.next }
|
146
|
+
end
|
147
|
+
primary_keys = threads.map{ |thread| thread.join; thread['id'] }
|
148
|
+
assert_includes 1, primary_keys
|
149
|
+
assert_includes 2, primary_keys
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
class NoRecordClassErrorTests < UnitTests
|
155
|
+
desc "NoRecordClassError"
|
156
|
+
setup do
|
157
|
+
@error_class = NoRecordClassError
|
158
|
+
end
|
159
|
+
subject{ @error_class }
|
160
|
+
|
161
|
+
should have_imeths :for_association
|
162
|
+
|
163
|
+
should "be a runtime error" do
|
164
|
+
assert_true subject < RuntimeError
|
165
|
+
end
|
166
|
+
|
167
|
+
should "know how to be built for a record reflection" do
|
168
|
+
record = TestFakeRecord.new
|
169
|
+
ar_association = record.association(:user)
|
170
|
+
error = subject.for_association(ar_association)
|
171
|
+
|
172
|
+
exp = "can't build 'user' association on #{TestFakeRecord} -- try " \
|
173
|
+
"manually setting it or building it via a stack if you've " \
|
174
|
+
"configured default associations"
|
175
|
+
assert_equal exp, error.message
|
176
|
+
|
177
|
+
ar_association = record.association(:parent)
|
178
|
+
error = subject.for_association(ar_association)
|
179
|
+
|
180
|
+
exp = "can't build 'parent' association on #{TestFakeRecord} -- try " \
|
181
|
+
"manually setting it, building it via a stack if you've " \
|
182
|
+
"configured default associations, or setting its 'parent_type' " \
|
183
|
+
"attribute"
|
184
|
+
assert_equal exp, error.message
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
class TestFakeRecord
|
190
|
+
include MR::FakeRecord
|
191
|
+
|
192
|
+
attribute :parent_type, :string, :null => true
|
193
|
+
attribute :parent_id, :integer, :null => true
|
194
|
+
attribute :user_id, :integer
|
195
|
+
|
196
|
+
belongs_to :parent, :polymorphic => true
|
197
|
+
belongs_to :user, :class_name => 'MR::Factory::RecordFactory::TestFakeRecord'
|
198
|
+
end
|
199
|
+
|
200
|
+
class TestFakeModel
|
201
|
+
include MR::Model
|
202
|
+
record_class TestFakeRecord
|
203
|
+
end
|
204
|
+
|
205
|
+
class TestReadModel
|
206
|
+
include MR::ReadModel
|
207
|
+
end
|
208
|
+
|
209
|
+
class TestReadModelStruct
|
210
|
+
include MR::ReadModelStruct
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/fake_query'
|
3
|
+
|
4
|
+
require 'mr/fake_record'
|
5
|
+
require 'mr/model'
|
6
|
+
require 'mr/query'
|
7
|
+
|
8
|
+
class MR::FakeQuery
|
9
|
+
|
10
|
+
class UnitTests < Assert::Context
|
11
|
+
desc "MR::FakeQuery"
|
12
|
+
setup do
|
13
|
+
# +1 so we always have at least 2 results
|
14
|
+
@results = (Factory.integer(3) + 1).times.map do
|
15
|
+
FakeTestModel.new.tap(&:save)
|
16
|
+
end
|
17
|
+
@query = MR::FakeQuery.new(@results)
|
18
|
+
end
|
19
|
+
subject{ @query }
|
20
|
+
|
21
|
+
should have_readers :results, :first, :count
|
22
|
+
should have_imeths :results!, :first!, :count!, :paged
|
23
|
+
|
24
|
+
should "know its results and count" do
|
25
|
+
assert_equal @results, subject.results
|
26
|
+
assert_equal @results.size, subject.count
|
27
|
+
end
|
28
|
+
|
29
|
+
should "default its results and count" do
|
30
|
+
query = MR::FakeQuery.new(nil)
|
31
|
+
assert_equal [], query.results
|
32
|
+
assert_equal 0, query.count
|
33
|
+
end
|
34
|
+
|
35
|
+
should "know its first result" do
|
36
|
+
assert_equal @results.first, subject.first
|
37
|
+
|
38
|
+
query = MR::FakeQuery.new([nil, []].sample)
|
39
|
+
assert_nil query.first
|
40
|
+
end
|
41
|
+
|
42
|
+
should "alias its results, first, and count methods" do
|
43
|
+
assert_same subject.results, subject.results!
|
44
|
+
assert_same subject.first, subject.first!
|
45
|
+
assert_same subject.count, subject.count!
|
46
|
+
end
|
47
|
+
|
48
|
+
should "return an instance of a `FakePagedQuery` with #paged" do
|
49
|
+
assert_instance_of MR::FakePagedQuery, subject.paged
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
class FakePagedQueryTests < UnitTests
|
55
|
+
desc "MR::FakePagedQuery"
|
56
|
+
setup do
|
57
|
+
@page_num = Factory.integer(@results.size)
|
58
|
+
@page_size = 1
|
59
|
+
|
60
|
+
@paged_query_class = MR::FakePagedQuery
|
61
|
+
@paged_query = @paged_query_class.new(@query, @page_num, @page_size)
|
62
|
+
end
|
63
|
+
subject{ @paged_query }
|
64
|
+
|
65
|
+
should have_readers :page_num, :page_size, :page_offset, :total_count
|
66
|
+
should have_imeths :total_count!, :has_next_page?, :is_last_page?
|
67
|
+
|
68
|
+
should "be a kind of MR::FakeQuery" do
|
69
|
+
assert_kind_of MR::FakeQuery, subject
|
70
|
+
end
|
71
|
+
|
72
|
+
should "know its page num/size/offset" do
|
73
|
+
assert_equal @page_num, subject.page_num
|
74
|
+
assert_equal @page_size, subject.page_size
|
75
|
+
exp = MR::PagedQuery::PageOffset.new(@page_num, @page_size)
|
76
|
+
assert_equal exp, subject.page_offset
|
77
|
+
end
|
78
|
+
|
79
|
+
should "know its paged results" do
|
80
|
+
exp = @results[subject.page_offset, subject.page_size]
|
81
|
+
assert_equal exp, subject.results
|
82
|
+
end
|
83
|
+
|
84
|
+
should "know its paged result count" do
|
85
|
+
assert_equal @page_size, subject.count
|
86
|
+
end
|
87
|
+
|
88
|
+
should "know its total number of results" do
|
89
|
+
assert_equal @results.size, subject.total_count
|
90
|
+
end
|
91
|
+
|
92
|
+
should "alias its total count" do
|
93
|
+
assert_same subject.total_count, subject.total_count!
|
94
|
+
end
|
95
|
+
|
96
|
+
should "know if it has a next page or is the last page" do
|
97
|
+
unpaged_results = @results.dup
|
98
|
+
Assert.stub(@results, :dup){ unpaged_results }
|
99
|
+
|
100
|
+
page_num = Factory.integer(10)
|
101
|
+
page_size = Factory.integer(10)
|
102
|
+
page_offset = MR::PagedQuery::PageOffset.new(page_num, page_size)
|
103
|
+
page_end = page_offset + page_size
|
104
|
+
|
105
|
+
total_count = Factory.integer(page_size - 1) + page_end
|
106
|
+
Assert.stub(unpaged_results, :size){ total_count }
|
107
|
+
paged_query = @paged_query_class.new(@query, page_num, page_size)
|
108
|
+
|
109
|
+
assert_true paged_query.has_next_page?
|
110
|
+
assert_false paged_query.is_last_page?
|
111
|
+
|
112
|
+
total_count = Factory.integer(page_size - 1) + page_offset
|
113
|
+
Assert.stub(unpaged_results, :size){ total_count }
|
114
|
+
paged_query = @paged_query_class.new(@query, page_num, page_size)
|
115
|
+
|
116
|
+
assert_false paged_query.has_next_page?
|
117
|
+
assert_true paged_query.is_last_page?
|
118
|
+
|
119
|
+
Assert.stub(unpaged_results, :size){ page_end }
|
120
|
+
paged_query = @paged_query_class.new(@query, page_num, page_size)
|
121
|
+
|
122
|
+
assert_false paged_query.has_next_page?
|
123
|
+
assert_true paged_query.is_last_page?
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
class FakeTestRecord
|
129
|
+
include MR::FakeRecord
|
130
|
+
end
|
131
|
+
|
132
|
+
class FakeTestModel
|
133
|
+
include MR::Model
|
134
|
+
record_class FakeTestRecord
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,585 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'mr/fake_record/associations'
|
3
|
+
|
4
|
+
require 'much-plugin'
|
5
|
+
require 'mr/fake_record'
|
6
|
+
|
7
|
+
module MR::FakeRecord::Associations
|
8
|
+
|
9
|
+
class UnitTests < Assert::Context
|
10
|
+
desc "MR::FakeRecord::Associations"
|
11
|
+
setup do
|
12
|
+
@fake_record_class = Class.new do
|
13
|
+
include MR::FakeRecord::Associations
|
14
|
+
end
|
15
|
+
end
|
16
|
+
subject{ @fake_record_class }
|
17
|
+
|
18
|
+
should have_imeths :reflections
|
19
|
+
should have_imeths :reflect_on_association, :reflect_on_all_associations
|
20
|
+
should have_imeths :belongs_to, :has_one, :has_many
|
21
|
+
|
22
|
+
should "use much-plugin" do
|
23
|
+
assert_includes MuchPlugin, MR::FakeRecord::Associations
|
24
|
+
end
|
25
|
+
|
26
|
+
should "include the fake record attributes mixin" do
|
27
|
+
assert_includes MR::FakeRecord::Attributes, subject
|
28
|
+
end
|
29
|
+
|
30
|
+
should "know its reflections" do
|
31
|
+
reflections = subject.reflections
|
32
|
+
assert_instance_of MR::FakeRecord::ReflectionSet, reflections
|
33
|
+
assert_same reflections, subject.reflections
|
34
|
+
end
|
35
|
+
|
36
|
+
should "allow adding belongs to associations" do
|
37
|
+
add_belongs_to_called_with = nil
|
38
|
+
Assert.stub(subject.reflections, :add_belongs_to) do |*args|
|
39
|
+
add_belongs_to_called_with = args
|
40
|
+
Assert.stub_send(subject.reflections, :add_belongs_to, *args)
|
41
|
+
end
|
42
|
+
association_name = Factory.string
|
43
|
+
options = { Factory.string => Factory.string }
|
44
|
+
subject.belongs_to(association_name, options)
|
45
|
+
|
46
|
+
exp = [subject, association_name, options]
|
47
|
+
assert_equal exp, add_belongs_to_called_with
|
48
|
+
end
|
49
|
+
|
50
|
+
should "allow adding has one associations" do
|
51
|
+
add_has_one_called_with = nil
|
52
|
+
Assert.stub(subject.reflections, :add_has_one) do |*args|
|
53
|
+
add_has_one_called_with = args
|
54
|
+
Assert.stub_send(subject.reflections, :add_has_one, *args)
|
55
|
+
end
|
56
|
+
association_name = Factory.string
|
57
|
+
options = { Factory.string => Factory.string }
|
58
|
+
subject.has_one(association_name, options)
|
59
|
+
|
60
|
+
exp = [subject, association_name, options]
|
61
|
+
assert_equal exp, add_has_one_called_with
|
62
|
+
end
|
63
|
+
|
64
|
+
should "allow adding has many associations" do
|
65
|
+
add_has_many_called_with = nil
|
66
|
+
Assert.stub(subject.reflections, :add_has_many) do |*args|
|
67
|
+
add_has_many_called_with = args
|
68
|
+
Assert.stub_send(subject.reflections, :add_has_many, *args)
|
69
|
+
end
|
70
|
+
association_name = Factory.string
|
71
|
+
options = { Factory.string => Factory.string }
|
72
|
+
subject.has_many(association_name, options)
|
73
|
+
|
74
|
+
exp = [subject, association_name, options]
|
75
|
+
assert_equal exp, add_has_many_called_with
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
class WithAssociationsTests < UnitTests
|
81
|
+
desc "with associations"
|
82
|
+
setup do
|
83
|
+
@fake_record_class.belongs_to :poly_test, :polymorphic => true
|
84
|
+
@fake_record_class.belongs_to :belongs_to_test, :class_name => FakeOneRecord.to_s
|
85
|
+
@fake_record_class.has_one :has_one_test, :class_name => FakeOneRecord.to_s
|
86
|
+
@fake_record_class.has_many :has_many_test, :class_name => FakeOneRecord.to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
should "return a specific reflection using `reflect_on_association`" do
|
90
|
+
name = [
|
91
|
+
:belongs_to_test,
|
92
|
+
:poly_test,
|
93
|
+
:has_one_test,
|
94
|
+
:has_many_test
|
95
|
+
].sample
|
96
|
+
reflection = subject.reflect_on_association(name)
|
97
|
+
|
98
|
+
assert_instance_of MR::FakeRecord::Reflection, reflection
|
99
|
+
assert_equal name, reflection.name
|
100
|
+
end
|
101
|
+
|
102
|
+
should "return all reflections using `reflect_on_all_associations`" do
|
103
|
+
reflections = subject.reflect_on_all_associations
|
104
|
+
assert_equal 4, reflections.size
|
105
|
+
reflections.each{ |r| assert_instance_of MR::FakeRecord::Reflection, r }
|
106
|
+
expected = [ :belongs_to_test, :poly_test, :has_one_test, :has_many_test ]
|
107
|
+
assert_equal expected, reflections.map(&:name)
|
108
|
+
end
|
109
|
+
|
110
|
+
should "only return specific kinds of reflections when a type is passed " \
|
111
|
+
"to `reflect_on_all_associations`" do
|
112
|
+
reflections = subject.reflect_on_all_associations(:belongs_to)
|
113
|
+
assert_equal [ :belongs_to_test, :poly_test ], reflections.map(&:name)
|
114
|
+
reflections = subject.reflect_on_all_associations(:has_many)
|
115
|
+
assert_equal [ :has_many_test ], reflections.map(&:name)
|
116
|
+
reflections = subject.reflect_on_all_associations(:has_one)
|
117
|
+
assert_equal [ :has_one_test ], reflections.map(&:name)
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class InstanceTests < UnitTests
|
123
|
+
desc "for a fake record instance"
|
124
|
+
setup do
|
125
|
+
@fake_record_class.belongs_to :test, :class_name => FakeOneRecord.to_s
|
126
|
+
@fake_record = @fake_record_class.new
|
127
|
+
end
|
128
|
+
subject{ @fake_record }
|
129
|
+
|
130
|
+
should have_imeths :association
|
131
|
+
|
132
|
+
should "return a matching association using `association`" do
|
133
|
+
association = subject.association(:test)
|
134
|
+
reflection = @fake_record_class.reflections.find(:test)
|
135
|
+
assert_equal reflection.macro, association.reflection.macro
|
136
|
+
assert_equal reflection.name, association.reflection.name
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
class ReflectionSetTests < UnitTests
|
142
|
+
desc "ReflectionSet"
|
143
|
+
setup do
|
144
|
+
@association_set = MR::FakeRecord::ReflectionSet.new
|
145
|
+
end
|
146
|
+
subject{ @association_set }
|
147
|
+
|
148
|
+
should have_imeths :belongs_to, :has_one, :has_many
|
149
|
+
should have_imeths :find, :all
|
150
|
+
should have_imeths :add_belongs_to, :add_has_one, :add_has_many
|
151
|
+
|
152
|
+
should "know how to add a belongs to" do
|
153
|
+
subject.add_belongs_to(@fake_record_class, :fake_one, {
|
154
|
+
:class_name => FakeOneRecord.to_s
|
155
|
+
})
|
156
|
+
|
157
|
+
assert_equal 1, subject.belongs_to.size
|
158
|
+
reflection = subject.belongs_to.first
|
159
|
+
assert_instance_of MR::FakeRecord::Reflection, reflection
|
160
|
+
assert_equal :fake_one, reflection.name
|
161
|
+
exp = {
|
162
|
+
:class_name => FakeOneRecord.to_s,
|
163
|
+
:foreign_key => 'fake_one_id'
|
164
|
+
}
|
165
|
+
assert_equal exp, reflection.options
|
166
|
+
|
167
|
+
fake_record = @fake_record_class.new
|
168
|
+
assert_respond_to :fake_one, fake_record
|
169
|
+
assert_respond_to :fake_one=, fake_record
|
170
|
+
end
|
171
|
+
|
172
|
+
should "allow passing a foreign key when adding a belongs to" do
|
173
|
+
foreign_key = Factory.string
|
174
|
+
subject.add_belongs_to(@fake_record_class, :fake_one, {
|
175
|
+
:class_name => FakeOneRecord.to_s,
|
176
|
+
:foreign_key => foreign_key
|
177
|
+
})
|
178
|
+
|
179
|
+
exp = {
|
180
|
+
:class_name => FakeOneRecord.to_s,
|
181
|
+
:foreign_key => foreign_key
|
182
|
+
}
|
183
|
+
assert_equal exp, subject.belongs_to.first.options
|
184
|
+
end
|
185
|
+
|
186
|
+
should "know how to add a polymorphic belongs to" do
|
187
|
+
subject.add_belongs_to(@fake_record_class, :fake_poly, {
|
188
|
+
:polymorphic => true
|
189
|
+
})
|
190
|
+
|
191
|
+
assert_equal 1, subject.belongs_to.size
|
192
|
+
reflection = subject.belongs_to.first
|
193
|
+
assert_instance_of MR::FakeRecord::Reflection, reflection
|
194
|
+
assert_equal :fake_poly, reflection.name
|
195
|
+
exp = {
|
196
|
+
:polymorphic => true,
|
197
|
+
:foreign_type => 'fake_poly_type',
|
198
|
+
:foreign_key => 'fake_poly_id'
|
199
|
+
}
|
200
|
+
assert_equal exp, reflection.options
|
201
|
+
|
202
|
+
fake_record = @fake_record_class.new
|
203
|
+
assert_respond_to :fake_poly, fake_record
|
204
|
+
assert_respond_to :fake_poly=, fake_record
|
205
|
+
end
|
206
|
+
|
207
|
+
should "allow passing a foreign type and key when adding a poly belongs to" do
|
208
|
+
foreign_type = Factory.string
|
209
|
+
foreign_key = Factory.string
|
210
|
+
subject.add_belongs_to(@fake_record_class, :fake_poly, {
|
211
|
+
:polymorphic => true,
|
212
|
+
:foreign_type => foreign_type,
|
213
|
+
:foreign_key => foreign_key
|
214
|
+
})
|
215
|
+
|
216
|
+
exp = {
|
217
|
+
:polymorphic => true,
|
218
|
+
:foreign_type => foreign_type,
|
219
|
+
:foreign_key => foreign_key
|
220
|
+
}
|
221
|
+
assert_equal exp, subject.belongs_to.first.options
|
222
|
+
end
|
223
|
+
|
224
|
+
should "know how to add a has one" do
|
225
|
+
subject.add_has_one(@fake_record_class, :fake_one, {
|
226
|
+
:class_name => FakeOneRecord.to_s
|
227
|
+
})
|
228
|
+
|
229
|
+
assert_equal 1, subject.has_one.size
|
230
|
+
reflection = subject.has_one.first
|
231
|
+
assert_instance_of MR::FakeRecord::Reflection, reflection
|
232
|
+
assert_equal :fake_one, reflection.name
|
233
|
+
exp = { :class_name => FakeOneRecord.to_s }
|
234
|
+
assert_equal exp, reflection.options
|
235
|
+
|
236
|
+
fake_record = @fake_record_class.new
|
237
|
+
assert_respond_to :fake_one, fake_record
|
238
|
+
assert_respond_to :fake_one=, fake_record
|
239
|
+
end
|
240
|
+
|
241
|
+
should "know how to add a has many" do
|
242
|
+
subject.add_has_many(@fake_record_class, :fake_ones, {
|
243
|
+
:class_name => FakeOneRecord.to_s
|
244
|
+
})
|
245
|
+
|
246
|
+
assert_equal 1, subject.has_many.size
|
247
|
+
reflection = subject.has_many.first
|
248
|
+
assert_instance_of MR::FakeRecord::Reflection, reflection
|
249
|
+
assert_equal :fake_ones, reflection.name
|
250
|
+
exp = { :class_name => FakeOneRecord.to_s }
|
251
|
+
assert_equal exp, reflection.options
|
252
|
+
|
253
|
+
fake_record = @fake_record_class.new
|
254
|
+
assert_respond_to :fake_ones, fake_record
|
255
|
+
assert_respond_to :fake_ones=, fake_record
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
class WithAssociationsOnReflectionSetTests < ReflectionSetTests
|
261
|
+
desc "with associations"
|
262
|
+
setup do
|
263
|
+
@association_set.add_belongs_to(@fake_record_class, :poly_belongs_to_test, {
|
264
|
+
:polymorphic => true
|
265
|
+
})
|
266
|
+
@association_set.add_belongs_to(@fake_record_class, :belongs_to_test, {
|
267
|
+
:class_name => FakeOneRecord.to_s
|
268
|
+
})
|
269
|
+
@association_set.add_has_one(@fake_record_class, :has_one_test, {
|
270
|
+
:class_name => FakeOneRecord.to_s
|
271
|
+
})
|
272
|
+
@association_set.add_has_many(@fake_record_class, :has_many_test, {
|
273
|
+
:class_name => FakeOneRecord.to_s
|
274
|
+
})
|
275
|
+
end
|
276
|
+
|
277
|
+
should "return all belongs to reflections sorted using `belongs_to`" do
|
278
|
+
reflections = subject.belongs_to
|
279
|
+
expected = [ :belongs_to_test, :poly_belongs_to_test ]
|
280
|
+
assert_equal expected, reflections.map(&:name)
|
281
|
+
end
|
282
|
+
|
283
|
+
should "return all has one reflections sorted using `has_one`" do
|
284
|
+
reflections = subject.has_one
|
285
|
+
assert_equal [ :has_one_test ], reflections.map(&:name)
|
286
|
+
end
|
287
|
+
|
288
|
+
should "return all has many reflections sorted using `has_many`" do
|
289
|
+
reflections = subject.has_many
|
290
|
+
assert_equal [ :has_many_test ], reflections.map(&:name)
|
291
|
+
end
|
292
|
+
|
293
|
+
should "find an reflection using `find`" do
|
294
|
+
reflection = subject.find(:belongs_to_test)
|
295
|
+
assert_equal :belongs_to_test, reflection.name
|
296
|
+
reflection = subject.find(:poly_belongs_to_test)
|
297
|
+
assert_equal :poly_belongs_to_test, reflection.name
|
298
|
+
reflection = subject.find(:has_one_test)
|
299
|
+
assert_equal :has_one_test, reflection.name
|
300
|
+
reflection = subject.find(:has_many_test)
|
301
|
+
assert_equal :has_many_test, reflection.name
|
302
|
+
|
303
|
+
assert_nil subject.find(:doesnt_exist)
|
304
|
+
end
|
305
|
+
|
306
|
+
should "return all reflections using `all`" do
|
307
|
+
reflections = subject.all
|
308
|
+
assert_equal 4, reflections.size
|
309
|
+
expected = [ :belongs_to_test, :poly_belongs_to_test, :has_one_test, :has_many_test ]
|
310
|
+
assert_equal expected, reflections.map(&:name)
|
311
|
+
end
|
312
|
+
|
313
|
+
should "return all matching reflections passing a type to `all`" do
|
314
|
+
reflections = subject.all(:belongs_to)
|
315
|
+
expected = [ :belongs_to_test, :poly_belongs_to_test ]
|
316
|
+
assert_equal expected, reflections.map(&:name)
|
317
|
+
reflections = subject.all(:has_many)
|
318
|
+
assert_equal [ :has_many_test ], reflections.map(&:name)
|
319
|
+
reflections = subject.all(:has_one)
|
320
|
+
assert_equal [ :has_one_test ], reflections.map(&:name)
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
class ReflectionTests < UnitTests
|
326
|
+
desc "MR::FakeRecord::Reflection"
|
327
|
+
setup do
|
328
|
+
@reflection_class = MR::FakeRecord::Reflection
|
329
|
+
@reflection = @reflection_class.new(:belongs_to, :parent, {
|
330
|
+
:class_name => FakeOneRecord.to_s,
|
331
|
+
:foreign_key => 'parent_id',
|
332
|
+
:foreign_type => 'parent_type'
|
333
|
+
})
|
334
|
+
end
|
335
|
+
subject{ @reflection }
|
336
|
+
|
337
|
+
should have_readers :reader_method_name, :writer_method_name
|
338
|
+
should have_readers :name, :macro, :options
|
339
|
+
should have_readers :foreign_key, :foreign_type
|
340
|
+
should have_imeths :association_class, :klass, :define_accessor_on
|
341
|
+
|
342
|
+
should "know its method names" do
|
343
|
+
assert_equal "parent", subject.reader_method_name
|
344
|
+
assert_equal "parent=", subject.writer_method_name
|
345
|
+
end
|
346
|
+
|
347
|
+
should "know its attributes" do
|
348
|
+
assert_equal :parent, subject.name
|
349
|
+
assert_equal :belongs_to, subject.macro
|
350
|
+
assert_equal 'parent_type', subject.foreign_type
|
351
|
+
assert_equal 'parent_id', subject.foreign_key
|
352
|
+
exp = {
|
353
|
+
:class_name => FakeOneRecord.to_s,
|
354
|
+
:foreign_key => subject.foreign_key,
|
355
|
+
:foreign_type => subject.foreign_type
|
356
|
+
}
|
357
|
+
assert_equal exp, subject.options
|
358
|
+
end
|
359
|
+
|
360
|
+
should "return its association class using `association_class`" do
|
361
|
+
reflection = @reflection_class.new(:belongs_to, :test, :polymorphic => true)
|
362
|
+
exp = MR::FakeRecord::PolymorphicBelongsToAssociation
|
363
|
+
assert_equal exp, reflection.association_class
|
364
|
+
|
365
|
+
reflection = @reflection_class.new(:belongs_to, :test)
|
366
|
+
exp = MR::FakeRecord::BelongsToAssociation
|
367
|
+
assert_equal exp, reflection.association_class
|
368
|
+
|
369
|
+
reflection = @reflection_class.new(:has_one, :test)
|
370
|
+
exp = MR::FakeRecord::HasOneAssociation
|
371
|
+
assert_equal exp, reflection.association_class
|
372
|
+
|
373
|
+
reflection = @reflection_class.new(:has_many, :test)
|
374
|
+
exp = MR::FakeRecord::HasManyAssociation
|
375
|
+
assert_equal exp, reflection.association_class
|
376
|
+
end
|
377
|
+
|
378
|
+
should "return its class names constantized with `klass`" do
|
379
|
+
assert_equal FakeOneRecord, subject.klass
|
380
|
+
end
|
381
|
+
|
382
|
+
should "define accessor methods using `define_accessor_on`" do
|
383
|
+
subject.define_accessor_on(@fake_record_class)
|
384
|
+
fake_record = @fake_record_class.new
|
385
|
+
|
386
|
+
assert_respond_to :parent, fake_record
|
387
|
+
assert_respond_to :parent=, fake_record
|
388
|
+
end
|
389
|
+
|
390
|
+
should "be sortable" do
|
391
|
+
reflections = [
|
392
|
+
MR::FakeRecord::Reflection.new(:belongs_to, Factory.string),
|
393
|
+
MR::FakeRecord::Reflection.new(:has_one, Factory.string),
|
394
|
+
MR::FakeRecord::Reflection.new(:has_many, Factory.string)
|
395
|
+
].shuffle.sort
|
396
|
+
exp = [:belongs_to, :has_many, :has_one]
|
397
|
+
assert_equal exp, reflections.map(&:macro)
|
398
|
+
end
|
399
|
+
|
400
|
+
end
|
401
|
+
|
402
|
+
class WithFakeRecordTests < UnitTests
|
403
|
+
setup do
|
404
|
+
@fake_record_class.class_eval do
|
405
|
+
attr_reader :test, :tests
|
406
|
+
attr_accessor :parent_type, :parent_id
|
407
|
+
end
|
408
|
+
@fake_record = @fake_record_class.new
|
409
|
+
end
|
410
|
+
subject{ @association }
|
411
|
+
|
412
|
+
end
|
413
|
+
|
414
|
+
class AssociationTests < WithFakeRecordTests
|
415
|
+
desc "Association"
|
416
|
+
setup do
|
417
|
+
@reflection = MR::FakeRecord::Reflection.new(:belongs_to, :test)
|
418
|
+
@association = MR::FakeRecord::Association.new(@fake_record, @reflection)
|
419
|
+
end
|
420
|
+
|
421
|
+
should have_readers :owner, :reflection
|
422
|
+
should have_imeths :read, :write, :klass
|
423
|
+
|
424
|
+
should "know its owner and reflection" do
|
425
|
+
assert_equal @fake_record, subject.owner
|
426
|
+
assert_equal @reflection, subject.reflection
|
427
|
+
end
|
428
|
+
|
429
|
+
should "return its reflection's klass using `klass`" do
|
430
|
+
assert_equal @reflection.klass, subject.klass
|
431
|
+
end
|
432
|
+
|
433
|
+
should "raise NotImplementedError using `read` and `write`" do
|
434
|
+
assert_raises(NotImplementedError){ subject.read }
|
435
|
+
assert_raises(NotImplementedError){ subject.write('test') }
|
436
|
+
end
|
437
|
+
|
438
|
+
should "be sortable" do
|
439
|
+
reflections = [
|
440
|
+
MR::FakeRecord::Reflection.new(:belongs_to, :belongs_to_test),
|
441
|
+
MR::FakeRecord::Reflection.new(:has_many, :has_many_test)
|
442
|
+
]
|
443
|
+
associations = reflections.map do |reflection|
|
444
|
+
MR::FakeRecord::Association.new(@fake_record, reflection)
|
445
|
+
end
|
446
|
+
association_names = associations.sort.map{ |a| a.reflection.name }
|
447
|
+
assert_equal reflections.sort.map(&:name), association_names
|
448
|
+
end
|
449
|
+
|
450
|
+
end
|
451
|
+
|
452
|
+
class OneToOneAssociationTests < WithFakeRecordTests
|
453
|
+
desc "OneToOneAssociation"
|
454
|
+
setup do
|
455
|
+
@reflection = MR::FakeRecord::Reflection.new(:belongs_to, :test)
|
456
|
+
@association = MR::FakeRecord::OneToOneAssociation.new(
|
457
|
+
@fake_record,
|
458
|
+
@reflection
|
459
|
+
)
|
460
|
+
end
|
461
|
+
|
462
|
+
should "be a kind of association" do
|
463
|
+
assert_kind_of MR::FakeRecord::Association, subject
|
464
|
+
end
|
465
|
+
|
466
|
+
should "read and write its value using `read` and `write`" do
|
467
|
+
associated_record = FakeOneRecord.new
|
468
|
+
subject.write(associated_record)
|
469
|
+
assert_same associated_record, @fake_record.test
|
470
|
+
assert_same @fake_record.test, subject.read
|
471
|
+
end
|
472
|
+
|
473
|
+
end
|
474
|
+
|
475
|
+
class OneToManyAssociationTests < WithFakeRecordTests
|
476
|
+
desc "OneToManyAssociation"
|
477
|
+
setup do
|
478
|
+
@reflection = MR::FakeRecord::Reflection.new(:has_many, :tests)
|
479
|
+
@association = MR::FakeRecord::OneToManyAssociation.new(
|
480
|
+
@fake_record,
|
481
|
+
@reflection
|
482
|
+
)
|
483
|
+
end
|
484
|
+
|
485
|
+
should "be a kind of association" do
|
486
|
+
assert_kind_of MR::FakeRecord::Association, subject
|
487
|
+
end
|
488
|
+
|
489
|
+
should "return an empty array when the association hasn't been set using `read`" do
|
490
|
+
assert_equal [], subject.read
|
491
|
+
end
|
492
|
+
|
493
|
+
should "read and write its value using `read` and `write`" do
|
494
|
+
associated_records = [FakeOneRecord.new]
|
495
|
+
subject.write(associated_records)
|
496
|
+
assert_equal associated_records, @fake_record.tests
|
497
|
+
assert_equal @fake_record.tests, subject.read
|
498
|
+
end
|
499
|
+
|
500
|
+
should "allow writing non-array values using `write`" do
|
501
|
+
associated_record = FakeOneRecord.new
|
502
|
+
subject.write(associated_record)
|
503
|
+
assert_equal [associated_record], @fake_record.tests
|
504
|
+
end
|
505
|
+
|
506
|
+
should "allow writing nil values using `write`" do
|
507
|
+
subject.write nil
|
508
|
+
assert_equal [], @fake_record.tests
|
509
|
+
end
|
510
|
+
|
511
|
+
end
|
512
|
+
|
513
|
+
class BelongsToAssociationTests < WithFakeRecordTests
|
514
|
+
desc "BelongsToAssociation"
|
515
|
+
setup do
|
516
|
+
@reflection = MR::FakeRecord::Reflection.new(:belongs_to, :parent, {
|
517
|
+
:foreign_key => 'parent_id'
|
518
|
+
})
|
519
|
+
@association = MR::FakeRecord::BelongsToAssociation.new(
|
520
|
+
@fake_record,
|
521
|
+
@reflection
|
522
|
+
)
|
523
|
+
end
|
524
|
+
|
525
|
+
should "be a kind of one to one association" do
|
526
|
+
assert_kind_of MR::FakeRecord::OneToOneAssociation, subject
|
527
|
+
end
|
528
|
+
|
529
|
+
should "write its foreign key using `write`" do
|
530
|
+
associated_record = FakeOneRecord.new.tap(&:save!)
|
531
|
+
subject.write(associated_record)
|
532
|
+
assert_equal associated_record.id, @fake_record.parent_id
|
533
|
+
end
|
534
|
+
|
535
|
+
should "allow writing nil values using `write`" do
|
536
|
+
subject.write nil
|
537
|
+
assert_equal nil, @fake_record.parent_id
|
538
|
+
end
|
539
|
+
|
540
|
+
end
|
541
|
+
|
542
|
+
class PolymorphicBelongsToAssociationTests < WithFakeRecordTests
|
543
|
+
desc "PolymorphicBelongsToAssociation"
|
544
|
+
setup do
|
545
|
+
@reflection = MR::FakeRecord::Reflection.new(:belongs_to, :parent, {
|
546
|
+
:foreign_type => 'parent_type',
|
547
|
+
:foreign_key => 'parent_id'
|
548
|
+
})
|
549
|
+
@association = MR::FakeRecord::PolymorphicBelongsToAssociation.new(
|
550
|
+
@fake_record,
|
551
|
+
@reflection
|
552
|
+
)
|
553
|
+
end
|
554
|
+
|
555
|
+
should "be a kind of belongs to association" do
|
556
|
+
assert_kind_of MR::FakeRecord::BelongsToAssociation, subject
|
557
|
+
end
|
558
|
+
|
559
|
+
should "constantize its foreign type using `klass`" do
|
560
|
+
@fake_record.parent_type = FakeOneRecord.to_s
|
561
|
+
assert_equal FakeOneRecord, subject.klass
|
562
|
+
end
|
563
|
+
|
564
|
+
should "return `nil` if its foreign type isn't set using `klass`" do
|
565
|
+
assert_nil subject.klass
|
566
|
+
end
|
567
|
+
|
568
|
+
should "write its foreign type using `write`" do
|
569
|
+
associated_record = FakeOneRecord.new.tap(&:save!)
|
570
|
+
subject.write(associated_record)
|
571
|
+
assert_equal FakeOneRecord.to_s, @fake_record.parent_type
|
572
|
+
end
|
573
|
+
|
574
|
+
should "allow writing nil values using `write`" do
|
575
|
+
subject.write nil
|
576
|
+
assert_equal nil, @fake_record.parent_type
|
577
|
+
end
|
578
|
+
|
579
|
+
end
|
580
|
+
|
581
|
+
class FakeOneRecord
|
582
|
+
include MR::FakeRecord
|
583
|
+
end
|
584
|
+
|
585
|
+
end
|