lookout-mongo_mapper 0.11.3
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.
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +26 -0
- data/bin/mmconsole +59 -0
- data/examples/attr_accessible.rb +22 -0
- data/examples/attr_protected.rb +22 -0
- data/examples/cache_key.rb +24 -0
- data/examples/custom_types.rb +24 -0
- data/examples/identity_map.rb +33 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +38 -0
- data/examples/querying.rb +35 -0
- data/examples/safe.rb +43 -0
- data/examples/scopes.rb +52 -0
- data/examples/validating/embedded_docs.rb +29 -0
- data/lib/mongo_mapper.rb +94 -0
- data/lib/mongo_mapper/connection.rb +96 -0
- data/lib/mongo_mapper/document.rb +42 -0
- data/lib/mongo_mapper/embedded_document.rb +32 -0
- data/lib/mongo_mapper/exceptions.rb +30 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +26 -0
- data/lib/mongo_mapper/extensions/object_id.rb +32 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +28 -0
- data/lib/mongo_mapper/locale/en.yml +5 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +22 -0
- data/lib/mongo_mapper/plugins/accessible.rb +52 -0
- data/lib/mongo_mapper/plugins/active_model.rb +18 -0
- data/lib/mongo_mapper/plugins/associations.rb +90 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/dirty.rb +60 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +13 -0
- data/lib/mongo_mapper/plugins/inspect.rb +16 -0
- data/lib/mongo_mapper/plugins/keys.rb +313 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
- data/lib/mongo_mapper/plugins/pagination.rb +16 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/querying.rb +165 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +36 -0
- data/lib/mongo_mapper/plugins/scopes.rb +27 -0
- data/lib/mongo_mapper/plugins/serialization.rb +109 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/touch.rb +18 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
- data/lib/mongo_mapper/plugins/validations.rb +86 -0
- data/lib/mongo_mapper/railtie.rb +48 -0
- data/lib/mongo_mapper/railtie/database.rake +65 -0
- data/lib/mongo_mapper/translation.rb +10 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
- data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
- data/test/functional/associations/test_many_documents_proxy.rb +866 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_as_proxy.rb +491 -0
- data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +383 -0
- data/test/functional/test_accessible.rb +198 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +77 -0
- data/test/functional/test_callbacks.rb +232 -0
- data/test/functional/test_dirty.rb +301 -0
- data/test/functional/test_document.rb +282 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +288 -0
- data/test/functional/test_equality.rb +20 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +50 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +537 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +201 -0
- data/test/functional/test_querying.rb +935 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +240 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_touch.rb +125 -0
- data/test/functional/test_userstamps.rb +44 -0
- data/test/functional/test_validations.rb +414 -0
- data/test/models.rb +261 -0
- data/test/support/railtie.rb +4 -0
- data/test/support/railtie/autoloaded.rb +2 -0
- data/test/support/railtie/not_autoloaded.rb +3 -0
- data/test/support/railtie/parent.rb +3 -0
- data/test/test_active_model_lint.rb +18 -0
- data/test/test_helper.rb +93 -0
- data/test/unit/associations/test_base.rb +146 -0
- data/test/unit/associations/test_belongs_to_association.rb +29 -0
- data/test/unit/associations/test_many_association.rb +63 -0
- data/test/unit/associations/test_one_association.rb +47 -0
- data/test/unit/associations/test_proxy.rb +100 -0
- data/test/unit/serializers/test_json_serializer.rb +216 -0
- data/test/unit/serializers/test_xml_serializer.rb +196 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_document.rb +249 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +682 -0
- data/test/unit/test_equality.rb +38 -0
- data/test/unit/test_exceptions.rb +12 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +47 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +65 -0
- data/test/unit/test_mongo_mapper.rb +143 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +89 -0
- data/test/unit/test_rails.rb +183 -0
- data/test/unit/test_rails_compatibility.rb +38 -0
- data/test/unit/test_rails_reflect_on_association.rb +118 -0
- data/test/unit/test_railtie.rb +66 -0
- data/test/unit/test_serialization.rb +166 -0
- data/test/unit/test_time_zones.rb +44 -0
- data/test/unit/test_translation.rb +27 -0
- data/test/unit/test_validations.rb +562 -0
- metadata +285 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'models'
|
|
3
|
+
|
|
4
|
+
class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
Room.collection.remove
|
|
7
|
+
Message.collection.remove
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "default reader to empty array" do
|
|
11
|
+
Room.new.messages.should == []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
should "add type key to polymorphic class base" do
|
|
15
|
+
Message.keys.keys.should include('_type')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
should "allow adding to assiciation like it was an array" do
|
|
19
|
+
room = Room.new
|
|
20
|
+
room.messages << Enter.new
|
|
21
|
+
room.messages.push Exit.new
|
|
22
|
+
room.messages.concat Exit.new
|
|
23
|
+
room.messages.size.should == 3
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
should "be able to replace the association" do
|
|
27
|
+
room = Room.create(:name => 'Lounge')
|
|
28
|
+
|
|
29
|
+
lambda {
|
|
30
|
+
room.messages = [
|
|
31
|
+
Enter.new(:body => 'John entered room', :position => 1),
|
|
32
|
+
Chat.new(:body => 'Heyyyoooo!', :position => 2),
|
|
33
|
+
Exit.new(:body => 'John exited room', :position => 3)
|
|
34
|
+
]
|
|
35
|
+
}.should change { Message.count }.by(3)
|
|
36
|
+
|
|
37
|
+
room = room.reload
|
|
38
|
+
messages = room.messages.all :order => "position"
|
|
39
|
+
messages.size.should == 3
|
|
40
|
+
messages[0].body.should == 'John entered room'
|
|
41
|
+
messages[1].body.should == 'Heyyyoooo!'
|
|
42
|
+
messages[2].body.should == 'John exited room'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
should "correctly store type when using <<, push and concat" do
|
|
46
|
+
room = Room.new
|
|
47
|
+
room.messages << Enter.new(:body => 'John entered the room', :position => 1)
|
|
48
|
+
room.messages.push Exit.new(:body => 'John entered the room', :position => 2)
|
|
49
|
+
room.messages.concat Chat.new(:body => 'Holla!' , :position => 3)
|
|
50
|
+
|
|
51
|
+
room = room.reload
|
|
52
|
+
messages = room.messages.all :order => "position"
|
|
53
|
+
messages[0]._type.should == 'Enter'
|
|
54
|
+
messages[1]._type.should == 'Exit'
|
|
55
|
+
messages[2]._type.should == 'Chat'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "build" do
|
|
59
|
+
should "assign foreign key" do
|
|
60
|
+
room = Room.create
|
|
61
|
+
message = room.messages.build
|
|
62
|
+
message.room_id.should == room._id
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
should "assign _type" do
|
|
66
|
+
room = Room.create
|
|
67
|
+
message = room.messages.build
|
|
68
|
+
message._type.should == 'Message'
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
should "allow assigning attributes" do
|
|
72
|
+
room = Room.create
|
|
73
|
+
message = room.messages.build(:body => 'Foo!')
|
|
74
|
+
message.body.should == 'Foo!'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "create" do
|
|
79
|
+
should "assign foreign key" do
|
|
80
|
+
room = Room.create
|
|
81
|
+
message = room.messages.create
|
|
82
|
+
message.room_id.should == room._id
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
should "assign _type" do
|
|
86
|
+
room = Room.create
|
|
87
|
+
message = room.messages.create
|
|
88
|
+
message._type.should == 'Message'
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
should "save record" do
|
|
92
|
+
room = Room.create
|
|
93
|
+
lambda {
|
|
94
|
+
room.messages.create
|
|
95
|
+
}.should change { Message.count }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
should "allow passing attributes" do
|
|
99
|
+
room = Room.create
|
|
100
|
+
message = room.messages.create(:body => 'Foo!')
|
|
101
|
+
message.body.should == 'Foo!'
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
context "count" do
|
|
106
|
+
should "work scoped to association" do
|
|
107
|
+
room = Room.create
|
|
108
|
+
3.times { room.messages.create }
|
|
109
|
+
|
|
110
|
+
other_room = Room.create
|
|
111
|
+
2.times { other_room.messages.create }
|
|
112
|
+
|
|
113
|
+
room.messages.count.should == 3
|
|
114
|
+
other_room.messages.count.should == 2
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
should "work with conditions" do
|
|
118
|
+
room = Room.create
|
|
119
|
+
room.messages.create(:body => 'Foo')
|
|
120
|
+
room.messages.create(:body => 'Other 1')
|
|
121
|
+
room.messages.create(:body => 'Other 2')
|
|
122
|
+
|
|
123
|
+
room.messages.count(:body => 'Foo').should == 1
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "Finding scoped to association" do
|
|
128
|
+
setup do
|
|
129
|
+
@lounge = Room.create(:name => 'Lounge')
|
|
130
|
+
@lm1 = Message.create(:body => 'Loungin!', :position => 1)
|
|
131
|
+
@lm2 = Message.create(:body => 'I love loungin!', :position => 2)
|
|
132
|
+
@lounge.messages = [@lm1, @lm2]
|
|
133
|
+
@lounge.save
|
|
134
|
+
|
|
135
|
+
@hall = Room.create(:name => 'Hall')
|
|
136
|
+
@hm1 = Message.create(:body => 'Do not fall in the hall', :position => 1)
|
|
137
|
+
@hm3 = Message.create(:body => 'Loungin!', :position => 3)
|
|
138
|
+
@hm2 = Message.create(:body => 'Hall the king!', :position => 2)
|
|
139
|
+
@hall.messages = [@hm1, @hm2, @hm3]
|
|
140
|
+
@hall.save
|
|
141
|
+
@hall.reload
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
context "dynamic finders" do
|
|
145
|
+
should "work with single key" do
|
|
146
|
+
@lounge.messages.find_by_position(1).should == @lm1
|
|
147
|
+
@hall.messages.find_by_position(2).should == @hm2
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
should "work with multiple keys" do
|
|
151
|
+
@lounge.messages.find_by_body_and_position('Loungin!', 1).should == @lm1
|
|
152
|
+
@lounge.messages.find_by_body_and_position('Loungin!', 2).should be_nil
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
should "raise error when using !" do
|
|
156
|
+
lambda {
|
|
157
|
+
@lounge.messages.find_by_position!(222)
|
|
158
|
+
}.should raise_error(MongoMapper::DocumentNotFound)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
context "find_or_create_by" do
|
|
162
|
+
should "not create document if found" do
|
|
163
|
+
lambda {
|
|
164
|
+
message = @lounge.messages.find_or_create_by_body('Loungin!')
|
|
165
|
+
message.room.should == @lounge
|
|
166
|
+
message.should == @lm1
|
|
167
|
+
}.should_not change { Message.count }
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
should "create document if not found" do
|
|
171
|
+
lambda {
|
|
172
|
+
message = @lounge.messages.find_or_create_by_body('Yo dawg!')
|
|
173
|
+
message.room.should == @lounge
|
|
174
|
+
message._type.should == 'Message'
|
|
175
|
+
}.should change { Message.count }.by(1)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context "with #all" do
|
|
181
|
+
should "work" do
|
|
182
|
+
@lounge.messages.all(:order => "position").should == [@lm1, @lm2]
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
should "work with conditions" do
|
|
186
|
+
messages = @lounge.messages.all(:body => 'Loungin!', :order => "position")
|
|
187
|
+
messages.should == [@lm1]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
should "work with order" do
|
|
191
|
+
messages = @lounge.messages.all(:order => 'position desc')
|
|
192
|
+
messages.should == [@lm2, @lm1]
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
context "with #first" do
|
|
197
|
+
should "work" do
|
|
198
|
+
@lounge.messages.first(:order => "position asc").should == @lm1
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
should "work with conditions" do
|
|
202
|
+
message = @lounge.messages.first(:body => 'I love loungin!', :order => "position asc")
|
|
203
|
+
message.should == @lm2
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
context "with #last" do
|
|
208
|
+
should "work" do
|
|
209
|
+
@lounge.messages.last(:order => "position asc").should == @lm2
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
should "work with conditions" do
|
|
213
|
+
message = @lounge.messages.last(:body => 'Loungin!', :order => "position asc")
|
|
214
|
+
message.should == @lm1
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
context "with one id" do
|
|
219
|
+
should "work for id in association" do
|
|
220
|
+
@lounge.messages.find(@lm2._id).should == @lm2
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
should "not work for id not in association" do
|
|
224
|
+
lambda {
|
|
225
|
+
@lounge.messages.find!(@hm2._id)
|
|
226
|
+
}.should raise_error(MongoMapper::DocumentNotFound)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
context "with query options/criteria" do
|
|
231
|
+
should "work with order on association" do
|
|
232
|
+
@lounge.messages.should == [@lm1, @lm2]
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
should "allow overriding the order provided to the association" do
|
|
236
|
+
@lounge.messages.all(:order => 'position').should == [@lm1, @lm2]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
should "allow using conditions on association" do
|
|
240
|
+
@hall.latest_messages.should == [@hm3, @hm2]
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context "with multiple ids" do
|
|
245
|
+
should "work for ids in association" do
|
|
246
|
+
messages = @lounge.messages.find(@lm1._id, @lm2._id)
|
|
247
|
+
messages.should == [@lm1, @lm2]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
should "not work for ids not in association" do
|
|
251
|
+
assert_raises(MongoMapper::DocumentNotFound) do
|
|
252
|
+
@lounge.messages.find!(@lm1._id, @lm2._id, @hm2._id)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context "with #paginate" do
|
|
258
|
+
setup do
|
|
259
|
+
@messages = @hall.messages.paginate(:per_page => 2, :page => 1, :order => 'position asc')
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
should "return total pages" do
|
|
263
|
+
@messages.total_pages.should == 2
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
should "return total entries" do
|
|
267
|
+
@messages.total_entries.should == 3
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
should "return the subject" do
|
|
271
|
+
@messages.should == [@hm1, @hm2]
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context "extending the association" do
|
|
277
|
+
should "work using a block passed to many" do
|
|
278
|
+
room = Room.new(:name => "Amazing Room")
|
|
279
|
+
messages = room.messages = [
|
|
280
|
+
Enter.new(:body => 'John entered room', :position => 3),
|
|
281
|
+
Chat.new(:body => 'Heyyyoooo!', :position => 4),
|
|
282
|
+
Exit.new(:body => 'John exited room', :position => 5),
|
|
283
|
+
Enter.new(:body => 'Steve entered room', :position => 6),
|
|
284
|
+
Chat.new(:body => 'Anyone there?', :position => 7),
|
|
285
|
+
Exit.new(:body => 'Steve exited room', :position => 8)
|
|
286
|
+
]
|
|
287
|
+
room.save
|
|
288
|
+
room.messages.older.should == messages[3..5]
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
should "work using many's :extend option" do
|
|
292
|
+
|
|
293
|
+
room = Room.new(:name => "Amazing Room")
|
|
294
|
+
accounts = room.accounts = [
|
|
295
|
+
Bot.new(:last_logged_in => 3.weeks.ago),
|
|
296
|
+
AccountUser.new(:last_logged_in => nil),
|
|
297
|
+
Bot.new(:last_logged_in => 1.week.ago)
|
|
298
|
+
]
|
|
299
|
+
room.save
|
|
300
|
+
room.accounts.inactive.should == [accounts[1]]
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
end
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
require 'models'
|
|
3
|
+
|
|
4
|
+
class OneAsProxyTest < Test::Unit::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
@post_class = Doc('Post')
|
|
7
|
+
@author_class = Doc('Author')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
should "default to nil" do
|
|
11
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
12
|
+
@post_class.new.author.nil?.should be_true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
should "return nil instead of a proxy" do
|
|
16
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
17
|
+
nil.should === @post_class.new.author
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
should "not define any keys" do
|
|
21
|
+
count = @post_class.keys.length
|
|
22
|
+
@post_class.one :author, :class => @author_class
|
|
23
|
+
@post_class.keys.length.should == count
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
should "allow assignment of associated document using a hash" do
|
|
27
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
28
|
+
|
|
29
|
+
post = @post_class.new('author' => { 'name' => 'Frank' })
|
|
30
|
+
post.author.name.should == 'Frank'
|
|
31
|
+
|
|
32
|
+
post.save.should be_true
|
|
33
|
+
post.reload
|
|
34
|
+
|
|
35
|
+
post.author.name.should == 'Frank'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should "only return a document with the correct type" do
|
|
39
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
40
|
+
post = @post_class.create
|
|
41
|
+
|
|
42
|
+
author = @author_class.create(:authorable_id => post.id, :authorable_type => "Nada")
|
|
43
|
+
post.reload.author.should be_nil
|
|
44
|
+
|
|
45
|
+
author = @author_class.create(:authorable_id => post.id, :authorable_type => "Post")
|
|
46
|
+
post.reload.author.should == author
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "replacing the association" do
|
|
50
|
+
context "with an object of the class" do
|
|
51
|
+
setup do
|
|
52
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
53
|
+
@post = @post_class.new
|
|
54
|
+
@author = @author_class.new(:name => 'Frank')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
should "work" do
|
|
58
|
+
@post.author = @author
|
|
59
|
+
@post.reload
|
|
60
|
+
|
|
61
|
+
@post.author.should == @author
|
|
62
|
+
@post.author.nil?.should be_false
|
|
63
|
+
|
|
64
|
+
new_author = @author_class.new(:name => 'Emily')
|
|
65
|
+
@post.author = new_author
|
|
66
|
+
@post.author.should == new_author
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
should "generate a new proxy instead of modifying the existing one" do
|
|
70
|
+
@post.author = @author
|
|
71
|
+
@post.reload
|
|
72
|
+
|
|
73
|
+
@post.author.should == @author
|
|
74
|
+
@post.author.nil?.should be_false
|
|
75
|
+
|
|
76
|
+
original_author = @post.author
|
|
77
|
+
original_author.name.should == 'Frank'
|
|
78
|
+
new_author = @author_class.new(:name => 'Emily')
|
|
79
|
+
@post.author = new_author
|
|
80
|
+
@post.author.should == new_author
|
|
81
|
+
|
|
82
|
+
original_author.name.should == 'Frank'
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
should "assign foreign key" do
|
|
86
|
+
@post.author = @author
|
|
87
|
+
@post.author.authorable_id.should == @post.id
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
should "assign _type" do
|
|
91
|
+
@post.author = @author
|
|
92
|
+
@post.author.authorable_type.should == "Post"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "with a Hash" do
|
|
97
|
+
setup do
|
|
98
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
99
|
+
@post = @post_class.new
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
should "convert to an object of the class and work" do
|
|
103
|
+
@post.author = {'name' => 'Frank'}
|
|
104
|
+
@post.reload
|
|
105
|
+
|
|
106
|
+
@post.author.name.should == 'Frank'
|
|
107
|
+
@post.author.nil?.should be_false
|
|
108
|
+
|
|
109
|
+
@post.author = {'name' => 'Emily'}
|
|
110
|
+
@post.author.name.should == 'Emily'
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
should "assign foreign key" do
|
|
114
|
+
@post.author = {'name' => 'Frank'}
|
|
115
|
+
@post.author.authorable_id.should == @post.id
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
should "assign _type" do
|
|
119
|
+
@post.author = {'name' => 'Frank'}
|
|
120
|
+
@post.author.authorable_type.should == "Post"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "with :dependent" do
|
|
125
|
+
context "=> delete" do
|
|
126
|
+
setup do
|
|
127
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :delete
|
|
128
|
+
|
|
129
|
+
@post = @post_class.create
|
|
130
|
+
@author = @author_class.new
|
|
131
|
+
@post.author = @author
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
should "call delete on the existing document" do
|
|
135
|
+
@author_class.any_instance.expects(:delete).once
|
|
136
|
+
@post.author = @author_class.new
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
should "remove the existing document from the database" do
|
|
140
|
+
@post.author = @author_class.new
|
|
141
|
+
lambda { @author.reload }.should raise_error(MongoMapper::DocumentNotFound)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
should "do nothing if it's the same document" do
|
|
145
|
+
@author_class.any_instance.expects(:delete).never
|
|
146
|
+
@post.author = @author
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
context "=> destory" do
|
|
151
|
+
setup do
|
|
152
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :destroy
|
|
153
|
+
|
|
154
|
+
@post = @post_class.create
|
|
155
|
+
@author = @author_class.new
|
|
156
|
+
@post.author = @author
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
should "call destroy the existing document" do
|
|
160
|
+
@author_class.any_instance.expects(:destroy).once
|
|
161
|
+
@post.author = @author_class.new
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
should "remove the existing document from the database" do
|
|
165
|
+
@post.author = @author_class.new
|
|
166
|
+
lambda { @author.reload }.should raise_error(MongoMapper::DocumentNotFound)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
should "do nothing if it's the same document" do
|
|
170
|
+
@author_class.any_instance.expects(:destroy).never
|
|
171
|
+
@post.author = @author
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "=> nullify" do
|
|
176
|
+
setup do
|
|
177
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :nullify
|
|
178
|
+
|
|
179
|
+
@post = @post_class.create
|
|
180
|
+
@author = @author_class.new
|
|
181
|
+
@post.author = @author
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
should "nullify the existing document" do
|
|
185
|
+
@author.reload
|
|
186
|
+
@author.authorable_id.should == @post.id
|
|
187
|
+
|
|
188
|
+
@post.author = @author_class.new
|
|
189
|
+
|
|
190
|
+
@author.reload
|
|
191
|
+
@author.authorable_id.should be_nil
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
should "work when it's the same document" do
|
|
195
|
+
old_author = @post.author
|
|
196
|
+
@post.author = @author
|
|
197
|
+
old_author.should == @post.author
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
should "nullify _type" do
|
|
201
|
+
@post.author = @author_class.new
|
|
202
|
+
@author.reload
|
|
203
|
+
@author.authorable_type.should be_nil
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
context "unspecified" do
|
|
208
|
+
setup do
|
|
209
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
210
|
+
|
|
211
|
+
@post = @post_class.create
|
|
212
|
+
@author = @author_class.new
|
|
213
|
+
@post.author = @author
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
should "nullify the existing document" do
|
|
217
|
+
@author.reload
|
|
218
|
+
@author.authorable_id.should == @post.id
|
|
219
|
+
|
|
220
|
+
@post.author = @author_class.new
|
|
221
|
+
|
|
222
|
+
@author.reload
|
|
223
|
+
@author.authorable_id.should be_nil
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
should "nullify _type" do
|
|
227
|
+
@post.author = @author_class.new
|
|
228
|
+
@author.reload
|
|
229
|
+
@author.authorable_type.should be_nil
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
context "with nil" do
|
|
235
|
+
setup do
|
|
236
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
237
|
+
|
|
238
|
+
@post = @post_class.new
|
|
239
|
+
@author = @author_class.new(:name => 'Frank')
|
|
240
|
+
@post.author = @author
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
should "nullify the existing document" do
|
|
244
|
+
@post.author = nil
|
|
245
|
+
@author.reload
|
|
246
|
+
@author.authorable_id.should be_nil
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
should "set the target to nil" do
|
|
250
|
+
@post.author = nil
|
|
251
|
+
@post.author.should == nil
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
should "nullify _type" do
|
|
255
|
+
@post.author = nil
|
|
256
|
+
@author.reload
|
|
257
|
+
@author.authorable_type.should be_nil
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
should "have boolean method for testing presence" do
|
|
263
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
264
|
+
|
|
265
|
+
post = @post_class.new
|
|
266
|
+
post.author?.should be_false
|
|
267
|
+
|
|
268
|
+
post.author = @author_class.new(:name => 'Frank')
|
|
269
|
+
post.author?.should be_true
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
should "work with criteria" do
|
|
273
|
+
@post_class.one :primary_author, :as => :authorable, :class => @author_class, :primary => true
|
|
274
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :primary => false
|
|
275
|
+
|
|
276
|
+
post = @post_class.create
|
|
277
|
+
author = @author_class.create(:name => 'Frank', :primary => false, :authorable_id => post.id, :authorable_type => 'Post')
|
|
278
|
+
primary = @author_class.create(:name => 'Bill', :primary => true, :authorable_id => post.id, :authorable_type => 'Post')
|
|
279
|
+
post.reload
|
|
280
|
+
post.author.should == author
|
|
281
|
+
post.primary_author.should == primary
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
should "unset the association" do
|
|
285
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
286
|
+
post = @post_class.create
|
|
287
|
+
author = @author_class.create
|
|
288
|
+
post.update_attributes!(:author => author)
|
|
289
|
+
post.reload
|
|
290
|
+
post.author = nil
|
|
291
|
+
post.author.nil?.should be_true
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
context "destroying parent with :dependent" do
|
|
295
|
+
context "=> destroy" do
|
|
296
|
+
setup do
|
|
297
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :destroy
|
|
298
|
+
|
|
299
|
+
@post = @post_class.create
|
|
300
|
+
@author = @author_class.new
|
|
301
|
+
@post.author = @author
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
should "should call destroy on the associated documents" do
|
|
305
|
+
@author_class.any_instance.expects(:destroy).once
|
|
306
|
+
@post.destroy
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
should "should remove the associated documents" do
|
|
310
|
+
@author_class.count.should == 1
|
|
311
|
+
@post.destroy
|
|
312
|
+
@post.author.should == nil
|
|
313
|
+
@author_class.count.should == 0
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
context "=> delete" do
|
|
318
|
+
setup do
|
|
319
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :delete
|
|
320
|
+
|
|
321
|
+
@post = @post_class.create
|
|
322
|
+
@author = @author_class.new
|
|
323
|
+
@post.author = @author
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
should "should call delete the associated documents" do
|
|
327
|
+
@author_class.any_instance.expects(:delete).once
|
|
328
|
+
@post.destroy
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
should "remove the associated documents" do
|
|
332
|
+
@author_class.count.should == 1
|
|
333
|
+
@post.destroy
|
|
334
|
+
@post.author.should == nil
|
|
335
|
+
@author_class.count.should == 0
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
context "=> nullify" do
|
|
340
|
+
setup do
|
|
341
|
+
@post_class.one :author, :as => :authorable, :class => @author_class, :dependent => :nullify
|
|
342
|
+
|
|
343
|
+
@post = @post_class.create
|
|
344
|
+
@author = @author_class.new
|
|
345
|
+
@post.author = @author
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
should "should nullify the relationship but not destroy the associated document" do
|
|
349
|
+
@author_class.count.should == 1
|
|
350
|
+
@post.destroy
|
|
351
|
+
@post.author.should == nil
|
|
352
|
+
@author_class.count.should == 1
|
|
353
|
+
|
|
354
|
+
@author_class.first.should == @author
|
|
355
|
+
@author.authorable_id.should == nil
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
should "nullify _type" do
|
|
359
|
+
@post.destroy
|
|
360
|
+
@author.authorable_type.should be_nil
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
context "unspecified" do
|
|
365
|
+
setup do
|
|
366
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
367
|
+
|
|
368
|
+
@post = @post_class.create
|
|
369
|
+
@author = @author_class.new
|
|
370
|
+
@post.author = @author
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
should "should nullify the relationship but not destroy the associated document" do
|
|
374
|
+
@author_class.count.should == 1
|
|
375
|
+
@post.destroy
|
|
376
|
+
@post.author.should == nil
|
|
377
|
+
@author_class.count.should == 1
|
|
378
|
+
|
|
379
|
+
@author_class.first.should == @author
|
|
380
|
+
@author.authorable_id.should == nil
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
should "nullify _type" do
|
|
384
|
+
@post.destroy
|
|
385
|
+
@author.authorable_type.should be_nil
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
context "#build" do
|
|
391
|
+
setup do
|
|
392
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
393
|
+
@post = @post_class.create
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
should "be able to build with attributes" do
|
|
397
|
+
author = @post.build_author(:name => 'John')
|
|
398
|
+
@post.author.should be_instance_of(@author_class)
|
|
399
|
+
@post.author.should be_new
|
|
400
|
+
@post.author.name.should == 'John'
|
|
401
|
+
@post.author.should == author
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
should "assign foreign key" do
|
|
405
|
+
@post.build_author
|
|
406
|
+
@post.author.authorable_id.should == @post.id
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
should "assign _type" do
|
|
410
|
+
@post.build_author
|
|
411
|
+
@post.author.authorable_type.should == 'Post'
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
context "#create" do
|
|
416
|
+
setup do
|
|
417
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
418
|
+
@post = @post_class.create
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
should "be able to create" do
|
|
422
|
+
author = @post.create_author(:name => 'John')
|
|
423
|
+
@post.author.should be_instance_of(@author_class)
|
|
424
|
+
@post.author.should_not be_new
|
|
425
|
+
@post.author.name.should == 'John'
|
|
426
|
+
@post.author.should == author
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
should "assign foreign key" do
|
|
430
|
+
@post.create_author
|
|
431
|
+
@post.author.authorable_id.should == @post.id
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
should "assign _type" do
|
|
435
|
+
@post.create_author
|
|
436
|
+
@post.author.authorable_type.should == 'Post'
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
context "#create!" do
|
|
441
|
+
setup do
|
|
442
|
+
@author_class.key :name, String, :required => true
|
|
443
|
+
@post_class.one :author, :as => :authorable, :class => @author_class
|
|
444
|
+
@post = @post_class.create
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
should "raise exception if invalid" do
|
|
448
|
+
assert_raises(MongoMapper::DocumentNotValid) do
|
|
449
|
+
@post.create_author!
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
should "work if valid" do
|
|
454
|
+
author = @post.create_author!(:name => 'John')
|
|
455
|
+
@post.author.should be_instance_of(@author_class)
|
|
456
|
+
@post.author.should_not be_new
|
|
457
|
+
@post.author.name.should == 'John'
|
|
458
|
+
@post.author.should == author
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
should "assign foreign key if valid" do
|
|
462
|
+
@post.create_author!(:name => 'John')
|
|
463
|
+
@post.author.authorable_id.should == @post.id
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
should "assign _type if valid" do
|
|
467
|
+
@post.create_author!(:name => 'John')
|
|
468
|
+
@post.author.authorable_type.should == 'Post'
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
context "namespaced foreign keys" do
|
|
473
|
+
setup do
|
|
474
|
+
News::Paper.one :article, :as => 'articleable', :class_name => 'News::Article'
|
|
475
|
+
News::Article.belongs_to :articleable, :polymorphic => true
|
|
476
|
+
|
|
477
|
+
@paper = News::Paper.create
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
should "work" do
|
|
481
|
+
@paper.create_article
|
|
482
|
+
@paper.article.class.should == News::Article
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
should "properly infer the foreign key" do
|
|
486
|
+
article = @paper.create_article
|
|
487
|
+
article.should respond_to(:articleable_id)
|
|
488
|
+
article.articleable_id.should == @paper.id
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
end
|