mr 0.35.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|