mongo_mapper 0.6.10 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -14
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongo_mapper.rb +48 -56
- data/lib/mongo_mapper/document.rb +136 -164
- data/lib/mongo_mapper/embedded_document.rb +29 -354
- data/lib/mongo_mapper/plugins.rb +31 -0
- data/lib/mongo_mapper/plugins/associations.rb +105 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
- data/lib/mongo_mapper/plugins/clone.rb +13 -0
- data/lib/mongo_mapper/plugins/descendants.rb +16 -0
- data/lib/mongo_mapper/plugins/dirty.rb +119 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
- data/lib/mongo_mapper/plugins/inspect.rb +14 -0
- data/lib/mongo_mapper/plugins/keys.rb +324 -0
- data/lib/mongo_mapper/plugins/logger.rb +17 -0
- data/lib/mongo_mapper/plugins/pagination.rb +24 -0
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/rails.rb +45 -0
- data/lib/mongo_mapper/plugins/serialization.rb +105 -0
- data/lib/mongo_mapper/plugins/validations.rb +46 -0
- data/lib/mongo_mapper/query.rb +130 -0
- data/lib/mongo_mapper/support.rb +40 -17
- data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
- data/lib/mongo_mapper/support/find.rb +77 -0
- data/mongo_mapper.gemspec +55 -38
- data/performance/read_write.rb +52 -0
- data/specs.watchr +23 -2
- data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
- data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
- data/test/functional/associations/test_many_documents_proxy.rb +2 -8
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
- data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
- data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
- data/test/functional/associations/test_one_proxy.rb +25 -10
- data/test/functional/test_binary.rb +2 -8
- data/test/functional/test_callbacks.rb +1 -5
- data/test/functional/test_dirty.rb +27 -23
- data/test/functional/test_document.rb +224 -165
- data/test/functional/test_embedded_document.rb +72 -82
- data/test/functional/test_identity_map.rb +508 -0
- data/test/functional/test_modifiers.rb +15 -5
- data/test/functional/test_pagination.rb +1 -3
- data/test/functional/test_protected.rb +155 -0
- data/test/functional/test_string_id_compatibility.rb +7 -12
- data/test/functional/test_validations.rb +26 -58
- data/test/models.rb +0 -39
- data/test/test_helper.rb +37 -3
- data/test/unit/associations/test_base.rb +5 -5
- data/test/unit/associations/test_proxy.rb +8 -6
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +71 -76
- data/test/unit/test_dynamic_finder.rb +27 -29
- data/test/unit/test_embedded_document.rb +555 -601
- data/test/unit/{test_key.rb → test_keys.rb} +2 -5
- data/test/unit/test_mongo_mapper.rb +69 -9
- data/test/unit/test_pagination.rb +40 -32
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
- data/test/unit/test_rails.rb +123 -0
- data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
- data/test/unit/test_support.rb +23 -7
- data/test/unit/test_time_zones.rb +3 -4
- data/test/unit/test_validations.rb +58 -17
- metadata +53 -36
- data/lib/mongo_mapper/associations.rb +0 -78
- data/lib/mongo_mapper/associations/base.rb +0 -119
- data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
- data/lib/mongo_mapper/associations/collection.rb +0 -19
- data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
- data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
- data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
- data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
- data/lib/mongo_mapper/associations/proxy.rb +0 -116
- data/lib/mongo_mapper/callbacks.rb +0 -61
- data/lib/mongo_mapper/dirty.rb +0 -117
- data/lib/mongo_mapper/dynamic_finder.rb +0 -74
- data/lib/mongo_mapper/finder_options.rb +0 -145
- data/lib/mongo_mapper/key.rb +0 -36
- data/lib/mongo_mapper/mongo_mapper.rb +0 -125
- data/lib/mongo_mapper/pagination.rb +0 -66
- data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
- data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
- data/lib/mongo_mapper/serialization.rb +0 -54
- data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
- data/lib/mongo_mapper/validations.rb +0 -39
- data/test/functional/test_rails_compatibility.rb +0 -25
@@ -176,22 +176,6 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
-
context "with :all" do
|
180
|
-
should "work" do
|
181
|
-
@lounge.messages.find(:all, :order => "position").should == [@lm1, @lm2]
|
182
|
-
end
|
183
|
-
|
184
|
-
should "work with conditions" do
|
185
|
-
messages = @lounge.messages.find(:all, :body => 'Loungin!', :order => "position")
|
186
|
-
messages.should == [@lm1]
|
187
|
-
end
|
188
|
-
|
189
|
-
should "work with order" do
|
190
|
-
messages = @lounge.messages.find(:all, :order => 'position desc')
|
191
|
-
messages.should == [@lm2, @lm1]
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
179
|
context "with #all" do
|
196
180
|
should "work" do
|
197
181
|
@lounge.messages.all(:order => "position").should == [@lm1, @lm2]
|
@@ -208,17 +192,6 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
208
192
|
end
|
209
193
|
end
|
210
194
|
|
211
|
-
context "with :first" do
|
212
|
-
should "work" do
|
213
|
-
@lounge.messages.find(:first, :order => "position asc").should == @lm1
|
214
|
-
end
|
215
|
-
|
216
|
-
should "work with conditions" do
|
217
|
-
message = @lounge.messages.find(:first, :body => 'I love loungin!', :order => "position asc")
|
218
|
-
message.should == @lm2
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
195
|
context "with #first" do
|
223
196
|
should "work" do
|
224
197
|
@lounge.messages.first(:order => "position asc").should == @lm1
|
@@ -230,17 +203,6 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
230
203
|
end
|
231
204
|
end
|
232
205
|
|
233
|
-
context "with :last" do
|
234
|
-
should "work" do
|
235
|
-
@lounge.messages.find(:last, :order => "position asc").should == @lm2
|
236
|
-
end
|
237
|
-
|
238
|
-
should "work with conditions" do
|
239
|
-
message = @lounge.messages.find(:last, :body => 'Loungin!', :order => "position asc")
|
240
|
-
message.should == @lm1
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
206
|
context "with #last" do
|
245
207
|
should "work" do
|
246
208
|
@lounge.messages.last(:order => "position asc").should == @lm2
|
@@ -285,9 +247,9 @@ class ManyPolymorphicProxyTest < Test::Unit::TestCase
|
|
285
247
|
end
|
286
248
|
|
287
249
|
should "not work for ids not in association" do
|
288
|
-
|
250
|
+
assert_raises(MongoMapper::DocumentNotFound) do
|
289
251
|
@lounge.messages.find!(@lm1._id, @lm2._id, @hm2._id)
|
290
|
-
|
252
|
+
end
|
291
253
|
end
|
292
254
|
end
|
293
255
|
|
@@ -2,18 +2,10 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class OneProxyTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@post_class =
|
6
|
-
|
7
|
-
def self.name; 'Post' end
|
8
|
-
end
|
9
|
-
|
10
|
-
@author_class = Class.new do
|
11
|
-
include MongoMapper::Document
|
5
|
+
@post_class = Doc('Post')
|
6
|
+
@author_class = Doc do
|
12
7
|
key :post_id, ObjectId
|
13
8
|
end
|
14
|
-
|
15
|
-
@post_class.collection.remove
|
16
|
-
@author_class.collection.remove
|
17
9
|
end
|
18
10
|
|
19
11
|
should "default to nil" do
|
@@ -21,6 +13,18 @@ class OneProxyTest < Test::Unit::TestCase
|
|
21
13
|
@post_class.new.author.nil?.should be_true
|
22
14
|
end
|
23
15
|
|
16
|
+
should "send object id to target" do
|
17
|
+
@post_class.one :author, :class => @author_class
|
18
|
+
|
19
|
+
post = @post_class.new
|
20
|
+
author = @author_class.new(:name => 'Frank')
|
21
|
+
post.author = author
|
22
|
+
author.save.should be_true
|
23
|
+
post.save.should be_true
|
24
|
+
|
25
|
+
post.author.object_id.should == post.author.target.object_id
|
26
|
+
end
|
27
|
+
|
24
28
|
should "be able to replace the association" do
|
25
29
|
@post_class.one :author, :class => @author_class
|
26
30
|
|
@@ -47,6 +51,17 @@ class OneProxyTest < Test::Unit::TestCase
|
|
47
51
|
post.author?.should be_true
|
48
52
|
end
|
49
53
|
|
54
|
+
should "work with criteria" do
|
55
|
+
@post_class.one :primary_author, :class => @author_class, :primary => true
|
56
|
+
@post_class.one :author, :class => @author_class
|
57
|
+
|
58
|
+
post = @post_class.create
|
59
|
+
author = @author_class.create(:name => 'Frank', :primary => false, :post_id => post.id)
|
60
|
+
primary = @author_class.create(:name => 'Bill', :primary => true, :post_id => post.id)
|
61
|
+
post.author.should == author
|
62
|
+
post.primary_author.should == primary
|
63
|
+
end
|
64
|
+
|
50
65
|
should "unset the association" do
|
51
66
|
@post_class.one :author, :class => @author_class
|
52
67
|
post = @post_class.new
|
@@ -2,12 +2,9 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class BinaryTest < Test::Unit::TestCase
|
4
4
|
should "serialize and deserialize correctly" do
|
5
|
-
klass =
|
6
|
-
include MongoMapper::Document
|
7
|
-
set_collection_name 'test'
|
5
|
+
klass = Doc do
|
8
6
|
key :contents, Binary
|
9
7
|
end
|
10
|
-
klass.collection.remove
|
11
8
|
|
12
9
|
doc = klass.new(:contents => '010101')
|
13
10
|
doc.save
|
@@ -18,12 +15,9 @@ class BinaryTest < Test::Unit::TestCase
|
|
18
15
|
|
19
16
|
context "Saving a document with a blank binary value" do
|
20
17
|
setup do
|
21
|
-
@document =
|
22
|
-
include MongoMapper::Document
|
23
|
-
set_collection_name 'test'
|
18
|
+
@document = Doc do
|
24
19
|
key :file, Binary
|
25
20
|
end
|
26
|
-
@document.collection.remove
|
27
21
|
end
|
28
22
|
|
29
23
|
should "not fail" do
|
@@ -3,10 +3,7 @@ require 'test_helper'
|
|
3
3
|
class CallbacksTest < Test::Unit::TestCase
|
4
4
|
context "Defining and running callbacks" do
|
5
5
|
setup do
|
6
|
-
@document =
|
7
|
-
include MongoMapper::Document
|
8
|
-
set_collection_name 'test'
|
9
|
-
|
6
|
+
@document = Doc do
|
10
7
|
key :name, String
|
11
8
|
|
12
9
|
[ :before_validation_on_create, :before_validation_on_update,
|
@@ -30,7 +27,6 @@ class CallbacksTest < Test::Unit::TestCase
|
|
30
27
|
@history = nil
|
31
28
|
end
|
32
29
|
end
|
33
|
-
@document.collection.remove
|
34
30
|
end
|
35
31
|
|
36
32
|
should "get the order right for creating documents" do
|
@@ -1,26 +1,17 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
require 'models'
|
3
2
|
|
4
3
|
class DirtyTest < Test::Unit::TestCase
|
5
4
|
def setup
|
6
|
-
@document =
|
7
|
-
include MongoMapper::Document
|
8
|
-
set_collection_name 'test'
|
9
|
-
key :phrase, String
|
10
|
-
end
|
11
|
-
@document.collection.remove
|
12
|
-
|
13
|
-
Status.collection.remove
|
14
|
-
Project.collection.remove
|
5
|
+
@document = Doc { key :phrase, String }
|
15
6
|
end
|
16
|
-
|
7
|
+
|
17
8
|
context "marking changes" do
|
18
9
|
should "not happen if there are none" do
|
19
10
|
doc = @document.new
|
20
11
|
doc.phrase_changed?.should be_false
|
21
12
|
doc.phrase_change.should be_nil
|
22
13
|
end
|
23
|
-
|
14
|
+
|
24
15
|
should "happen when change happens" do
|
25
16
|
doc = @document.new
|
26
17
|
doc.phrase = 'Golly Gee Willikers Batman'
|
@@ -28,12 +19,12 @@ class DirtyTest < Test::Unit::TestCase
|
|
28
19
|
doc.phrase_was.should be_nil
|
29
20
|
doc.phrase_change.should == [nil, 'Golly Gee Willikers Batman']
|
30
21
|
end
|
31
|
-
|
22
|
+
|
32
23
|
should "happen when initializing" do
|
33
24
|
doc = @document.new(:phrase => 'Foo')
|
34
25
|
doc.changed?.should be_true
|
35
26
|
end
|
36
|
-
|
27
|
+
|
37
28
|
should "clear changes on save" do
|
38
29
|
doc = @document.new
|
39
30
|
doc.phrase = 'Golly Gee Willikers Batman'
|
@@ -42,7 +33,7 @@ class DirtyTest < Test::Unit::TestCase
|
|
42
33
|
doc.phrase_changed?.should_not be_true
|
43
34
|
doc.phrase_change.should be_nil
|
44
35
|
end
|
45
|
-
|
36
|
+
|
46
37
|
should "clear changes on save!" do
|
47
38
|
doc = @document.new
|
48
39
|
doc.phrase = 'Golly Gee Willikers Batman'
|
@@ -51,15 +42,18 @@ class DirtyTest < Test::Unit::TestCase
|
|
51
42
|
doc.phrase_changed?.should_not be_true
|
52
43
|
doc.phrase_change.should be_nil
|
53
44
|
end
|
54
|
-
|
45
|
+
|
55
46
|
should "not happen when loading from database" do
|
56
47
|
doc = @document.create(:phrase => 'Foo')
|
48
|
+
doc = @document.find(doc.id)
|
49
|
+
|
50
|
+
doc.changed?.should be_false
|
57
51
|
doc.phrase = 'Fart'
|
58
52
|
doc.changed?.should be_true
|
59
53
|
doc.reload
|
60
54
|
doc.changed?.should be_false
|
61
55
|
end
|
62
|
-
|
56
|
+
|
63
57
|
should "happen if changed after loading from database" do
|
64
58
|
doc = @document.create(:phrase => 'Foo')
|
65
59
|
doc.reload
|
@@ -68,7 +62,7 @@ class DirtyTest < Test::Unit::TestCase
|
|
68
62
|
doc.changed?.should be_true
|
69
63
|
end
|
70
64
|
end
|
71
|
-
|
65
|
+
|
72
66
|
context "blank new value and type integer" do
|
73
67
|
should "not mark changes" do
|
74
68
|
@document.key :age, Integer
|
@@ -115,7 +109,7 @@ class DirtyTest < Test::Unit::TestCase
|
|
115
109
|
should "be hash of keys with values of changes if there are changes" do
|
116
110
|
doc = @document.new
|
117
111
|
doc.phrase = 'A penny saved is a penny earned.'
|
118
|
-
doc.changes.should ==
|
112
|
+
doc.changes['phrase'].should == [nil, 'A penny saved is a penny earned.']
|
119
113
|
end
|
120
114
|
end
|
121
115
|
|
@@ -150,10 +144,20 @@ class DirtyTest < Test::Unit::TestCase
|
|
150
144
|
|
151
145
|
context "changing a foreign key through association" do
|
152
146
|
should "mark changes" do
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
147
|
+
project_class = Doc do
|
148
|
+
key :name, String
|
149
|
+
end
|
150
|
+
|
151
|
+
milestone_class = Doc do
|
152
|
+
key :project_id, ObjectId
|
153
|
+
key :name, String
|
154
|
+
end
|
155
|
+
milestone_class.belongs_to :project, :class => project_class
|
156
|
+
|
157
|
+
milestone = milestone_class.create(:name => 'Launch')
|
158
|
+
milestone.project = project_class.create(:name => 'Harmony')
|
159
|
+
milestone.changed?.should be_true
|
160
|
+
milestone.changed.should == %w(project_id)
|
157
161
|
end
|
158
162
|
end
|
159
163
|
end
|
@@ -3,8 +3,7 @@ require 'models'
|
|
3
3
|
|
4
4
|
class DocumentTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
@document =
|
7
|
-
include MongoMapper::Document
|
6
|
+
@document = Doc do
|
8
7
|
set_collection_name 'users'
|
9
8
|
|
10
9
|
key :first_name, String
|
@@ -12,10 +11,9 @@ class DocumentTest < Test::Unit::TestCase
|
|
12
11
|
key :age, Integer
|
13
12
|
key :date, Date
|
14
13
|
end
|
15
|
-
@document.collection.remove
|
16
14
|
end
|
17
15
|
|
18
|
-
context "
|
16
|
+
context "array key" do
|
19
17
|
setup do
|
20
18
|
@document.key :tags, Array
|
21
19
|
end
|
@@ -62,7 +60,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
65
|
-
context "
|
63
|
+
context "hash key" do
|
66
64
|
setup do
|
67
65
|
@document.key :foo, Hash
|
68
66
|
end
|
@@ -97,7 +95,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
|
-
context "
|
98
|
+
context "custom type key with default" do
|
101
99
|
setup do
|
102
100
|
@document.key :window, WindowSize, :default => WindowSize.new(600, 480)
|
103
101
|
end
|
@@ -143,12 +141,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
143
141
|
end
|
144
142
|
|
145
143
|
should "not fail if no attributes provided" do
|
146
|
-
document =
|
147
|
-
include MongoMapper::Document
|
148
|
-
set_collection_name 'test'
|
149
|
-
end
|
150
|
-
document.collection.remove
|
151
|
-
|
144
|
+
document = Doc()
|
152
145
|
lambda { document.create }.should change { document.count }.by(1)
|
153
146
|
end
|
154
147
|
end
|
@@ -246,7 +239,19 @@ class DocumentTest < Test::Unit::TestCase
|
|
246
239
|
end
|
247
240
|
|
248
241
|
should "raise document not found if nothing provided for find!" do
|
249
|
-
|
242
|
+
assert_raises(MongoMapper::DocumentNotFound) do
|
243
|
+
@document.find!
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
should "raise error if trying to find with :all, :first, or :last" do
|
248
|
+
[:all, :first, :last].each do |m|
|
249
|
+
assert_raises(ArgumentError) { @document.find(m) }
|
250
|
+
end
|
251
|
+
|
252
|
+
[:all, :first, :last].each do |m|
|
253
|
+
assert_raises(ArgumentError) { @document.find!(m) }
|
254
|
+
end
|
250
255
|
end
|
251
256
|
|
252
257
|
context "(with a single id)" do
|
@@ -259,9 +264,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
259
264
|
end
|
260
265
|
|
261
266
|
should "raise error if document not found with find!" do
|
262
|
-
|
263
|
-
@document.find!(123)
|
264
|
-
}.should raise_error(MongoMapper::DocumentNotFound)
|
267
|
+
assert_raises(MongoMapper::DocumentNotFound) { @document.find!(123) }
|
265
268
|
end
|
266
269
|
end
|
267
270
|
|
@@ -274,7 +277,17 @@ class DocumentTest < Test::Unit::TestCase
|
|
274
277
|
@document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
|
275
278
|
end
|
276
279
|
|
277
|
-
should "
|
280
|
+
should "compact not found when using find" do
|
281
|
+
@document.find(@doc1._id, 1234).should == [@doc1]
|
282
|
+
end
|
283
|
+
|
284
|
+
should "raise error if not all found when using find!" do
|
285
|
+
assert_raises(MongoMapper::DocumentNotFound) do
|
286
|
+
@document.find!(@doc1._id, 1234)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
should "return array if array with one element" do
|
278
291
|
@document.find([@doc1._id]).should == [@doc1]
|
279
292
|
end
|
280
293
|
end
|
@@ -284,43 +297,21 @@ class DocumentTest < Test::Unit::TestCase
|
|
284
297
|
@document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
|
285
298
|
end
|
286
299
|
|
287
|
-
context "
|
288
|
-
should "find all documents" do
|
289
|
-
@document.find(:all, :order => 'first_name').should == [@doc1, @doc3, @doc2]
|
290
|
-
end
|
291
|
-
|
292
|
-
should "be able to add conditions" do
|
293
|
-
@document.find(:all, :first_name => 'John').should == [@doc1]
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
context "(with #all)" do
|
300
|
+
context "#all" do
|
298
301
|
should "find all documents based on criteria" do
|
299
302
|
@document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
|
300
303
|
@document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
|
301
304
|
end
|
302
305
|
end
|
303
306
|
|
304
|
-
context "
|
305
|
-
should "find first document" do
|
306
|
-
@document.find(:first, :order => 'first_name').should == @doc1
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
context "(with #first)" do
|
307
|
+
context "#first" do
|
311
308
|
should "find first document based on criteria" do
|
312
309
|
@document.first(:order => 'first_name').should == @doc1
|
313
310
|
@document.first(:age => 28).should == @doc2
|
314
311
|
end
|
315
312
|
end
|
316
313
|
|
317
|
-
context "
|
318
|
-
should "find last document" do
|
319
|
-
@document.find(:last, :order => 'age').should == @doc2
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
context "(with #last)" do
|
314
|
+
context "#last" do
|
324
315
|
should "find last document based on criteria" do
|
325
316
|
@document.last(:order => 'age').should == @doc2
|
326
317
|
@document.last(:order => 'age', :age => 28).should == @doc2
|
@@ -331,7 +322,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
331
322
|
end
|
332
323
|
end
|
333
324
|
|
334
|
-
context "
|
325
|
+
context "#find_by..." do
|
335
326
|
should "find document based on argument" do
|
336
327
|
@document.find_by_first_name('John').should == @doc1
|
337
328
|
@document.find_by_last_name('Nunemaker', :order => 'age desc').should == @doc1
|
@@ -347,7 +338,19 @@ class DocumentTest < Test::Unit::TestCase
|
|
347
338
|
end
|
348
339
|
end
|
349
340
|
|
350
|
-
context "
|
341
|
+
context "#find_each" do
|
342
|
+
should "yield all documents found, based on criteria" do
|
343
|
+
yield_documents = []
|
344
|
+
@document.find_each(:order => "first_name") {|doc| yield_documents << doc }
|
345
|
+
yield_documents.should == [@doc1, @doc3, @doc2]
|
346
|
+
|
347
|
+
yield_documents = []
|
348
|
+
@document.find_each(:last_name => 'Nunemaker', :order => 'age desc') {|doc| yield_documents << doc }
|
349
|
+
yield_documents.should == [@doc1, @doc3]
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context "dynamic finders" do
|
351
354
|
should "find document based on all arguments" do
|
352
355
|
@document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
|
353
356
|
end
|
@@ -400,7 +403,44 @@ class DocumentTest < Test::Unit::TestCase
|
|
400
403
|
end
|
401
404
|
|
402
405
|
should "return nil if document not found" do
|
403
|
-
@document.find_by_id(1234).should
|
406
|
+
@document.find_by_id(1234).should be_nil
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
context "first_or_create" do
|
411
|
+
should "find if exists" do
|
412
|
+
created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
|
413
|
+
lambda {
|
414
|
+
found = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
|
415
|
+
found.should == created
|
416
|
+
}.should_not change { @document.count }
|
417
|
+
end
|
418
|
+
|
419
|
+
should "create if not found" do
|
420
|
+
lambda {
|
421
|
+
created = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
|
422
|
+
created.first_name.should == 'John'
|
423
|
+
created.last_name.should == 'Nunemaker'
|
424
|
+
}.should change { @document.count }.by(1)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
context "first_or_new" do
|
429
|
+
should "find if exists" do
|
430
|
+
created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
|
431
|
+
lambda {
|
432
|
+
found = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
|
433
|
+
found.should == created
|
434
|
+
}.should_not change { @document.count }
|
435
|
+
end
|
436
|
+
|
437
|
+
should "initialize if not found" do
|
438
|
+
lambda {
|
439
|
+
created = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
|
440
|
+
created.first_name.should == 'John'
|
441
|
+
created.last_name.should == 'Nunemaker'
|
442
|
+
created.should be_new
|
443
|
+
}.should_not change { @document.count }
|
404
444
|
end
|
405
445
|
end
|
406
446
|
|
@@ -541,11 +581,9 @@ class DocumentTest < Test::Unit::TestCase
|
|
541
581
|
end
|
542
582
|
|
543
583
|
should "return 0 if the collection does not exist" do
|
544
|
-
klass =
|
545
|
-
include MongoMapper::Document
|
584
|
+
klass = Doc do
|
546
585
|
set_collection_name 'foobarbazwickdoesnotexist'
|
547
586
|
end
|
548
|
-
@document.collection.remove
|
549
587
|
|
550
588
|
klass.count.should == 0
|
551
589
|
end
|
@@ -567,10 +605,10 @@ class DocumentTest < Test::Unit::TestCase
|
|
567
605
|
@document.new.database.should == @document.database
|
568
606
|
end
|
569
607
|
|
570
|
-
context "#
|
608
|
+
context "#update_attributes (new document)" do
|
571
609
|
setup do
|
572
610
|
@doc = @document.new(:first_name => 'John', :age => '27')
|
573
|
-
@doc.
|
611
|
+
@doc.update_attributes(:first_name => 'Johnny', :age => 30)
|
574
612
|
end
|
575
613
|
|
576
614
|
should "insert document into the collection" do
|
@@ -582,46 +620,27 @@ class DocumentTest < Test::Unit::TestCase
|
|
582
620
|
end
|
583
621
|
|
584
622
|
should "save attributes" do
|
585
|
-
@doc.first_name.should == '
|
586
|
-
@doc.age.should ==
|
623
|
+
@doc.first_name.should == 'Johnny'
|
624
|
+
@doc.age.should == 30
|
587
625
|
end
|
588
626
|
|
589
627
|
should "update attributes in the database" do
|
590
628
|
doc = @doc.reload
|
591
629
|
doc.should == @doc
|
592
|
-
doc.first_name.should == '
|
593
|
-
doc.age.should ==
|
594
|
-
end
|
595
|
-
|
596
|
-
should "allow to add custom attributes to the document" do
|
597
|
-
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
|
598
|
-
@doc.save
|
599
|
-
doc = @doc.reload
|
600
|
-
doc.gender.should == 'male'
|
601
|
-
doc.tags.should == [1, "2"]
|
602
|
-
end
|
603
|
-
|
604
|
-
should "allow to use custom methods to assign properties" do
|
605
|
-
person = RealPerson.new(:realname => 'David')
|
606
|
-
person.save
|
607
|
-
person.reload.name.should == 'David'
|
630
|
+
doc.first_name.should == 'Johnny'
|
631
|
+
doc.age.should == 30
|
608
632
|
end
|
609
633
|
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
doc.save
|
614
|
-
doc.date.should == Date.new(2009, 12, 1)
|
615
|
-
end
|
634
|
+
should "allow updating custom attributes" do
|
635
|
+
@doc.update_attributes(:gender => 'mALe')
|
636
|
+
@doc.reload.gender.should == 'mALe'
|
616
637
|
end
|
617
638
|
end
|
618
639
|
|
619
|
-
context "#
|
640
|
+
context "#update_attributes (existing document)" do
|
620
641
|
setup do
|
621
642
|
@doc = @document.create(:first_name => 'John', :age => '27')
|
622
|
-
@doc.first_name
|
623
|
-
@doc.age = 30
|
624
|
-
@doc.save
|
643
|
+
@doc.update_attributes(:first_name => 'Johnny', :age => 30)
|
625
644
|
end
|
626
645
|
|
627
646
|
should "not insert document into collection" do
|
@@ -638,19 +657,26 @@ class DocumentTest < Test::Unit::TestCase
|
|
638
657
|
doc.first_name.should == 'Johnny'
|
639
658
|
doc.age.should == 30
|
640
659
|
end
|
660
|
+
end
|
641
661
|
|
642
|
-
|
643
|
-
|
644
|
-
@
|
645
|
-
@doc.save
|
646
|
-
@doc.reload.gender.should == 'Male'
|
662
|
+
context "#update_attributes (return value)" do
|
663
|
+
setup do
|
664
|
+
@document.key :foo, String, :required => true
|
647
665
|
end
|
648
|
-
end
|
649
666
|
|
650
|
-
|
667
|
+
should "be true if document valid" do
|
668
|
+
@document.new.update_attributes(:foo => 'bar').should be_true
|
669
|
+
end
|
670
|
+
|
671
|
+
should "be false if document not valid" do
|
672
|
+
@document.new.update_attributes({}).should be_false
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
context "#save (new document)" do
|
651
677
|
setup do
|
652
678
|
@doc = @document.new(:first_name => 'John', :age => '27')
|
653
|
-
@doc.
|
679
|
+
@doc.save
|
654
680
|
end
|
655
681
|
|
656
682
|
should "insert document into the collection" do
|
@@ -662,27 +688,54 @@ class DocumentTest < Test::Unit::TestCase
|
|
662
688
|
end
|
663
689
|
|
664
690
|
should "save attributes" do
|
665
|
-
@doc.first_name.should == '
|
666
|
-
@doc.age.should ==
|
691
|
+
@doc.first_name.should == 'John'
|
692
|
+
@doc.age.should == 27
|
667
693
|
end
|
668
694
|
|
669
695
|
should "update attributes in the database" do
|
670
696
|
doc = @doc.reload
|
671
697
|
doc.should == @doc
|
672
|
-
doc.first_name.should == '
|
673
|
-
doc.age.should ==
|
698
|
+
doc.first_name.should == 'John'
|
699
|
+
doc.age.should == 27
|
674
700
|
end
|
675
701
|
|
676
|
-
should "allow
|
677
|
-
@doc.
|
678
|
-
@doc.
|
702
|
+
should "allow to add custom attributes to the document" do
|
703
|
+
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
|
704
|
+
@doc.save
|
705
|
+
doc = @doc.reload
|
706
|
+
doc.gender.should == 'male'
|
707
|
+
doc.tags.should == [1, "2"]
|
708
|
+
end
|
709
|
+
|
710
|
+
should "allow to use custom methods to assign properties" do
|
711
|
+
klass = Doc do
|
712
|
+
key :name, String
|
713
|
+
|
714
|
+
def realname=(value)
|
715
|
+
self.name = value
|
716
|
+
end
|
717
|
+
end
|
718
|
+
|
719
|
+
person = klass.new(:realname => 'David')
|
720
|
+
person.save
|
721
|
+
person.reload.name.should == 'David'
|
722
|
+
end
|
723
|
+
|
724
|
+
context "with key of type date" do
|
725
|
+
should "save the date value as a Time object" do
|
726
|
+
doc = @document.new(:first_name => 'John', :age => '27', :date => "12/01/2009")
|
727
|
+
doc.save
|
728
|
+
doc.date.should == Date.new(2009, 12, 1)
|
729
|
+
end
|
679
730
|
end
|
680
731
|
end
|
681
732
|
|
682
|
-
context "#
|
733
|
+
context "#save (existing document)" do
|
683
734
|
setup do
|
684
735
|
@doc = @document.create(:first_name => 'John', :age => '27')
|
685
|
-
@doc.
|
736
|
+
@doc.first_name = 'Johnny'
|
737
|
+
@doc.age = 30
|
738
|
+
@doc.save
|
686
739
|
end
|
687
740
|
|
688
741
|
should "not insert document into collection" do
|
@@ -699,68 +752,82 @@ class DocumentTest < Test::Unit::TestCase
|
|
699
752
|
doc.first_name.should == 'Johnny'
|
700
753
|
doc.age.should == 30
|
701
754
|
end
|
702
|
-
end
|
703
|
-
|
704
|
-
context "#update_attributes" do
|
705
|
-
setup do
|
706
|
-
@document.key :foo, String, :required => true
|
707
|
-
end
|
708
|
-
|
709
|
-
should "return true if document valid" do
|
710
|
-
@document.new.update_attributes(:foo => 'bar').should be_true
|
711
|
-
end
|
712
755
|
|
713
|
-
should "
|
714
|
-
@document.new
|
756
|
+
should "allow updating custom attributes" do
|
757
|
+
@doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male')
|
758
|
+
@doc.gender = 'Male'
|
759
|
+
@doc.save
|
760
|
+
@doc.reload.gender.should == 'Male'
|
715
761
|
end
|
716
762
|
end
|
717
|
-
|
763
|
+
|
718
764
|
context "#save (with validations off)" do
|
719
765
|
setup do
|
720
|
-
@document =
|
721
|
-
include MongoMapper::Document
|
722
|
-
set_collection_name 'test'
|
766
|
+
@document = Doc do
|
723
767
|
key :name, String, :required => true
|
724
768
|
end
|
725
|
-
@document.collection.remove
|
726
769
|
end
|
727
770
|
|
728
|
-
should "insert document" do
|
771
|
+
should "insert invalid document" do
|
729
772
|
doc = @document.new
|
773
|
+
doc.expects(:valid?).never
|
730
774
|
doc.save(:validate => false)
|
731
775
|
@document.count.should == 1
|
732
776
|
end
|
733
|
-
|
734
|
-
should "work with false passed to save" do
|
735
|
-
doc = @document.new
|
736
|
-
doc.save(false)
|
737
|
-
@document.count.should == 1
|
738
|
-
end
|
739
777
|
end
|
740
778
|
|
741
779
|
context "#save (with options)" do
|
742
780
|
setup do
|
743
|
-
|
744
|
-
|
745
|
-
@document = Class.new do
|
746
|
-
include MongoMapper::Document
|
747
|
-
set_collection_name 'test'
|
781
|
+
@document = Doc do
|
748
782
|
key :name, String
|
749
|
-
|
783
|
+
set_collection_name 'test_indexes'
|
750
784
|
end
|
751
|
-
@document
|
752
|
-
|
753
|
-
MongoMapper.ensure_indexes!
|
785
|
+
drop_indexes(@document)
|
786
|
+
@document.ensure_index :name, :unique => true
|
754
787
|
end
|
755
|
-
|
788
|
+
|
756
789
|
should "allow passing safe" do
|
757
|
-
|
758
|
-
doc.save
|
759
|
-
|
790
|
+
@document.create(:name => 'John')
|
760
791
|
assert_raises(Mongo::OperationFailure) do
|
761
792
|
@document.new(:name => 'John').save(:safe => true)
|
762
793
|
end
|
763
794
|
end
|
795
|
+
|
796
|
+
should "raise argument error if options has unsupported key" do
|
797
|
+
assert_raises(ArgumentError) do
|
798
|
+
@document.new.save(:foo => true)
|
799
|
+
end
|
800
|
+
end
|
801
|
+
end
|
802
|
+
|
803
|
+
context "#save! (with options)" do
|
804
|
+
setup do
|
805
|
+
@document = Doc do
|
806
|
+
key :name, String
|
807
|
+
set_collection_name 'test_indexes'
|
808
|
+
end
|
809
|
+
drop_indexes(@document)
|
810
|
+
@document.ensure_index :name, :unique => true
|
811
|
+
end
|
812
|
+
|
813
|
+
should "allow passing safe" do
|
814
|
+
@document.create(:name => 'John')
|
815
|
+
assert_raises(Mongo::OperationFailure) do
|
816
|
+
@document.new(:name => 'John').save!(:safe => true)
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
should "raise argument error if options has unsupported key" do
|
821
|
+
assert_raises(ArgumentError) do
|
822
|
+
@document.new.save!(:foo => true)
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
should "raise argument error if using validate as that would be pointless with save!" do
|
827
|
+
assert_raises(ArgumentError) do
|
828
|
+
@document.new.save!(:validate => false)
|
829
|
+
end
|
830
|
+
end
|
764
831
|
end
|
765
832
|
|
766
833
|
context "#destroy" do
|
@@ -843,7 +910,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
843
910
|
@parent.save
|
844
911
|
@daughter.save
|
845
912
|
|
846
|
-
collection = DocParent.
|
913
|
+
collection = DocParent.all
|
847
914
|
collection.size.should == 2
|
848
915
|
collection.first.should be_kind_of(DocParent)
|
849
916
|
collection.first.name.should == "Daddy Warbucks"
|
@@ -967,11 +1034,19 @@ class DocumentTest < Test::Unit::TestCase
|
|
967
1034
|
|
968
1035
|
context "timestamping" do
|
969
1036
|
setup do
|
970
|
-
@
|
1037
|
+
@klass = Doc do
|
1038
|
+
set_collection_name 'users'
|
1039
|
+
|
1040
|
+
key :first_name, String
|
1041
|
+
key :last_name, String
|
1042
|
+
key :age, Integer
|
1043
|
+
key :date, Date
|
1044
|
+
end
|
1045
|
+
@klass.timestamps!
|
971
1046
|
end
|
972
1047
|
|
973
1048
|
should "set created_at and updated_at on create" do
|
974
|
-
doc = @
|
1049
|
+
doc = @klass.new(:first_name => 'John', :age => 27)
|
975
1050
|
doc.created_at.should be(nil)
|
976
1051
|
doc.updated_at.should be(nil)
|
977
1052
|
doc.save
|
@@ -981,7 +1056,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
981
1056
|
|
982
1057
|
should "not overwrite created_at if it already exists" do
|
983
1058
|
original_created_at = 1.month.ago
|
984
|
-
doc = @
|
1059
|
+
doc = @klass.new(:first_name => 'John', :age => 27, :created_at => original_created_at)
|
985
1060
|
doc.created_at.to_i.should == original_created_at.to_i
|
986
1061
|
doc.updated_at.should be_nil
|
987
1062
|
doc.save
|
@@ -990,7 +1065,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
990
1065
|
end
|
991
1066
|
|
992
1067
|
should "set updated_at on field update but leave created_at alone" do
|
993
|
-
doc = @
|
1068
|
+
doc = @klass.create(:first_name => 'John', :age => 27)
|
994
1069
|
old_created_at = doc.created_at
|
995
1070
|
old_updated_at = doc.updated_at
|
996
1071
|
doc.first_name = 'Johnny'
|
@@ -1004,12 +1079,12 @@ class DocumentTest < Test::Unit::TestCase
|
|
1004
1079
|
end
|
1005
1080
|
|
1006
1081
|
should "set updated_at on document update but leave created_at alone" do
|
1007
|
-
doc = @
|
1082
|
+
doc = @klass.create(:first_name => 'John', :age => 27)
|
1008
1083
|
old_created_at = doc.created_at
|
1009
1084
|
old_updated_at = doc.updated_at
|
1010
1085
|
|
1011
1086
|
Timecop.freeze(Time.now + 5.seconds) do
|
1012
|
-
@
|
1087
|
+
@klass.update(doc._id, { :first_name => 'Johnny' })
|
1013
1088
|
end
|
1014
1089
|
|
1015
1090
|
doc = doc.reload
|
@@ -1040,7 +1115,7 @@ class DocumentTest < Test::Unit::TestCase
|
|
1040
1115
|
end
|
1041
1116
|
end
|
1042
1117
|
|
1043
|
-
context "#
|
1118
|
+
context "#exists?" do
|
1044
1119
|
setup do
|
1045
1120
|
@doc = @document.create(:first_name => "James", :age => 27)
|
1046
1121
|
end
|
@@ -1065,14 +1140,11 @@ class DocumentTest < Test::Unit::TestCase
|
|
1065
1140
|
|
1066
1141
|
context "#reload" do
|
1067
1142
|
setup do
|
1068
|
-
@foo_class =
|
1069
|
-
include MongoMapper::Document
|
1143
|
+
@foo_class = Doc do
|
1070
1144
|
key :name
|
1071
1145
|
end
|
1072
|
-
@foo_class.collection.remove
|
1073
1146
|
|
1074
|
-
@bar_class =
|
1075
|
-
include MongoMapper::EmbeddedDocument
|
1147
|
+
@bar_class = EDoc do
|
1076
1148
|
key :name
|
1077
1149
|
end
|
1078
1150
|
|
@@ -1107,19 +1179,14 @@ class DocumentTest < Test::Unit::TestCase
|
|
1107
1179
|
should "return self" do
|
1108
1180
|
@instance.reload.object_id.should == @instance.object_id
|
1109
1181
|
end
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
@document.key :_id, String
|
1115
|
-
doc = @document.new(:id => '1234')
|
1116
|
-
doc.using_custom_id?.should be_true
|
1117
|
-
doc.save.should be_true
|
1118
|
-
doc.using_custom_id?.should be_false
|
1182
|
+
|
1183
|
+
should "raise DocumentNotFound if not found" do
|
1184
|
+
@instance.destroy
|
1185
|
+
assert_raises(MongoMapper::DocumentNotFound) { @instance.reload }
|
1119
1186
|
end
|
1120
1187
|
end
|
1121
1188
|
|
1122
|
-
context "
|
1189
|
+
context "database has keys not defined in model" do
|
1123
1190
|
setup do
|
1124
1191
|
@id = Mongo::ObjectID.new
|
1125
1192
|
@document.collection.insert({
|
@@ -1144,28 +1211,22 @@ class DocumentTest < Test::Unit::TestCase
|
|
1144
1211
|
|
1145
1212
|
context "Indexing" do
|
1146
1213
|
setup do
|
1147
|
-
|
1148
|
-
@document.collection.drop_indexes
|
1214
|
+
drop_indexes(@document)
|
1149
1215
|
end
|
1150
1216
|
|
1151
1217
|
should "allow creating index for a key" do
|
1152
1218
|
@document.ensure_index :first_name
|
1153
|
-
MongoMapper.ensure_indexes!
|
1154
|
-
|
1155
1219
|
@document.should have_index('first_name_1')
|
1156
1220
|
end
|
1157
1221
|
|
1158
1222
|
should "allow creating unique index for a key" do
|
1159
1223
|
@document.ensure_index :first_name, :unique => true
|
1160
|
-
MongoMapper.ensure_indexes!
|
1161
|
-
|
1162
1224
|
@document.should have_index('first_name_1')
|
1163
1225
|
end
|
1164
1226
|
|
1165
1227
|
should "allow creating index on multiple keys" do
|
1166
1228
|
@document.ensure_index [[:first_name, 1], [:last_name, -1]]
|
1167
|
-
|
1168
|
-
|
1229
|
+
|
1169
1230
|
# order is different for different versions of ruby so instead of
|
1170
1231
|
# just checking have_index('first_name_1_last_name_-1') I'm checking
|
1171
1232
|
# the values of the indexes to make sure the index creation was successful
|
@@ -1177,8 +1238,6 @@ class DocumentTest < Test::Unit::TestCase
|
|
1177
1238
|
|
1178
1239
|
should "work with :index shortcut when defining key" do
|
1179
1240
|
@document.key :father, String, :index => true
|
1180
|
-
MongoMapper.ensure_indexes!
|
1181
|
-
|
1182
1241
|
@document.should have_index('father_1')
|
1183
1242
|
end
|
1184
1243
|
end
|