mongo_mapper 0.6.10 → 0.7.0

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.
Files changed (106) hide show
  1. data/README.rdoc +5 -14
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongo_mapper.rb +48 -56
  5. data/lib/mongo_mapper/document.rb +136 -164
  6. data/lib/mongo_mapper/embedded_document.rb +29 -354
  7. data/lib/mongo_mapper/plugins.rb +31 -0
  8. data/lib/mongo_mapper/plugins/associations.rb +105 -0
  9. data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
  10. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  11. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  12. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  13. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
  14. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  15. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  16. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  17. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  18. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  19. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  20. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  21. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  22. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  23. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  24. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  25. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  26. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  27. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  28. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  29. data/lib/mongo_mapper/plugins/keys.rb +324 -0
  30. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  31. data/lib/mongo_mapper/plugins/pagination.rb +24 -0
  32. data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
  33. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  34. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  35. data/lib/mongo_mapper/plugins/serialization.rb +105 -0
  36. data/lib/mongo_mapper/plugins/validations.rb +46 -0
  37. data/lib/mongo_mapper/query.rb +130 -0
  38. data/lib/mongo_mapper/support.rb +40 -17
  39. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  40. data/lib/mongo_mapper/support/find.rb +77 -0
  41. data/mongo_mapper.gemspec +55 -38
  42. data/performance/read_write.rb +52 -0
  43. data/specs.watchr +23 -2
  44. data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
  45. data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
  46. data/test/functional/associations/test_many_documents_proxy.rb +2 -8
  47. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
  48. data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
  49. data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
  50. data/test/functional/associations/test_one_proxy.rb +25 -10
  51. data/test/functional/test_binary.rb +2 -8
  52. data/test/functional/test_callbacks.rb +1 -5
  53. data/test/functional/test_dirty.rb +27 -23
  54. data/test/functional/test_document.rb +224 -165
  55. data/test/functional/test_embedded_document.rb +72 -82
  56. data/test/functional/test_identity_map.rb +508 -0
  57. data/test/functional/test_modifiers.rb +15 -5
  58. data/test/functional/test_pagination.rb +1 -3
  59. data/test/functional/test_protected.rb +155 -0
  60. data/test/functional/test_string_id_compatibility.rb +7 -12
  61. data/test/functional/test_validations.rb +26 -58
  62. data/test/models.rb +0 -39
  63. data/test/test_helper.rb +37 -3
  64. data/test/unit/associations/test_base.rb +5 -5
  65. data/test/unit/associations/test_proxy.rb +8 -6
  66. data/test/unit/test_descendant_appends.rb +71 -0
  67. data/test/unit/test_document.rb +71 -76
  68. data/test/unit/test_dynamic_finder.rb +27 -29
  69. data/test/unit/test_embedded_document.rb +555 -601
  70. data/test/unit/{test_key.rb → test_keys.rb} +2 -5
  71. data/test/unit/test_mongo_mapper.rb +69 -9
  72. data/test/unit/test_pagination.rb +40 -32
  73. data/test/unit/test_plugins.rb +50 -0
  74. data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
  75. data/test/unit/test_rails.rb +123 -0
  76. data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
  77. data/test/unit/test_support.rb +23 -7
  78. data/test/unit/test_time_zones.rb +3 -4
  79. data/test/unit/test_validations.rb +58 -17
  80. metadata +53 -36
  81. data/lib/mongo_mapper/associations.rb +0 -78
  82. data/lib/mongo_mapper/associations/base.rb +0 -119
  83. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  84. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  85. data/lib/mongo_mapper/associations/collection.rb +0 -19
  86. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  87. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  88. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  89. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  90. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  91. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  92. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  93. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  94. data/lib/mongo_mapper/callbacks.rb +0 -61
  95. data/lib/mongo_mapper/dirty.rb +0 -117
  96. data/lib/mongo_mapper/dynamic_finder.rb +0 -74
  97. data/lib/mongo_mapper/finder_options.rb +0 -145
  98. data/lib/mongo_mapper/key.rb +0 -36
  99. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  100. data/lib/mongo_mapper/pagination.rb +0 -66
  101. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  102. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  103. data/lib/mongo_mapper/serialization.rb +0 -54
  104. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  105. data/lib/mongo_mapper/validations.rb +0 -39
  106. data/test/functional/test_rails_compatibility.rb +0 -25
@@ -1,6 +1,27 @@
1
+ def growl(title, msg, img)
2
+ %x{growlnotify -m #{ msg.inspect} -t #{title.inspect} --image ~/.watchr/#{img}.png}
3
+ end
4
+
5
+ def form_growl_message(str)
6
+ results = str.split("\n").last
7
+ if results =~ /[1-9]\s(failure|error)s?/
8
+ growl "Test Results", "#{results}", "fail"
9
+ elsif results != ""
10
+ growl "Test Results", "#{results}", "pass"
11
+ end
12
+ end
13
+
1
14
  def run(cmd)
2
15
  puts(cmd)
3
- system(cmd)
16
+ output = ""
17
+ IO.popen(cmd) do |com|
18
+ com.each_char do |c|
19
+ print c
20
+ output << c
21
+ $stdout.flush
22
+ end
23
+ end
24
+ form_growl_message output
4
25
  end
5
26
 
6
27
  def run_test_file(file)
@@ -17,7 +38,7 @@ end
17
38
 
18
39
  watch('test/test_helper\.rb') { system('clear'); run_all_tests }
19
40
  watch('test/.*/test_.*\.rb') { |m| system('clear'); run_test_file(m[0]) }
20
- watch('lib/.*') { |m| related_test_files(m[0]).each { |file| system('clear'); run_test_file(file) } }
41
+ watch('lib/.*') { |m| related_test_files(m[0]).each { |file| run_test_file(file) } }
21
42
 
22
43
  # Ctrl-\
23
44
  Signal.trap('QUIT') do
@@ -3,24 +3,26 @@ require 'models'
3
3
 
4
4
  class BelongsToProxyTest < Test::Unit::TestCase
5
5
  def setup
6
- @post_class = Class.new do
7
- include MongoMapper::Document
8
- end
9
-
10
- @comment_class = Class.new do
11
- include MongoMapper::Document
6
+ @post_class = Doc()
7
+ @comment_class = Doc do
12
8
  key :post_id, String
13
9
  end
14
- @comment_class.belongs_to :post, :class => @post_class
15
10
 
16
- @post_class.collection.remove
17
- @comment_class.collection.remove
11
+ @comment_class.belongs_to :post, :class => @post_class
18
12
  end
19
13
 
20
14
  should "default to nil" do
21
15
  @comment_class.new.post.nil?.should be_true
22
16
  end
23
17
 
18
+ should "send object id to target" do
19
+ post = @post_class.new(:name => 'mongomapper')
20
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
21
+ comment.save
22
+
23
+ comment.post.object_id.should == comment.post.target.object_id
24
+ end
25
+
24
26
  should "have boolean presence method" do
25
27
  comment = @comment_class.new(:name => 'Foo!')
26
28
  comment.post?.should be_false
@@ -78,7 +80,7 @@ class BelongsToProxyTest < Test::Unit::TestCase
78
80
  setup do
79
81
  Property.key :thing_id, ObjectId
80
82
  Property.belongs_to :thing, :dependent => :destroy
81
- Thing.has_many :properties
83
+ Thing.many :properties
82
84
 
83
85
  @thing = Thing.create(:name => "Tree")
84
86
  @property1 = Property.create
@@ -131,23 +131,6 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
131
131
  @post2.save
132
132
  end
133
133
 
134
- context "with :all" do
135
- should "work" do
136
- @post.comments.find(:all).should include(@comment1)
137
- @post.comments.find(:all).should include(@comment2)
138
- end
139
-
140
- should "work with conditions" do
141
- comments = @post.comments.find(:all, :body => 'comment1')
142
- comments.should == [@comment1]
143
- end
144
-
145
- should "work with order" do
146
- comments = @post.comments.find(:all, :order => 'body desc')
147
- comments.should == [@comment2, @comment1]
148
- end
149
- end
150
-
151
134
  context "with #all" do
152
135
  should "work" do
153
136
  @post.comments.all.should include(@comment1)
@@ -171,9 +154,9 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
171
154
  end
172
155
 
173
156
  should "not work for id not in association" do
174
- lambda {
157
+ assert_raises(MongoMapper::DocumentNotFound) do
175
158
  @post.comments.find!(@comment5._id)
176
- }.should raise_error(MongoMapper::DocumentNotFound)
159
+ end
177
160
  end
178
161
  end
179
162
 
@@ -184,9 +167,9 @@ class ManyDocumentsAsProxyTest < Test::Unit::TestCase
184
167
  end
185
168
 
186
169
  should "not work for ids not in association" do
187
- lambda {
170
+ assert_raises(MongoMapper::DocumentNotFound) do
188
171
  @post.comments.find!(@comment1._id, @comment2._id, @comment4._id)
189
- }.should raise_error(MongoMapper::DocumentNotFound)
172
+ end
190
173
  end
191
174
  end
192
175
 
@@ -242,36 +242,30 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
242
242
 
243
243
  context "all" do
244
244
  should "work" do
245
- @project1.statuses.find(:all, :order => "position asc").should == [@brand_new, @complete]
246
245
  @project1.statuses.all(:order => "position asc").should == [@brand_new, @complete]
247
246
  end
248
247
 
249
248
  should "work with conditions" do
250
- @project1.statuses.find(:all, :name => 'Complete').should == [@complete]
251
249
  @project1.statuses.all(:name => 'Complete').should == [@complete]
252
250
  end
253
251
  end
254
252
 
255
253
  context "first" do
256
254
  should "work" do
257
- @project1.statuses.find(:first, :order => 'name').should == @complete
258
255
  @project1.statuses.first(:order => 'name').should == @complete
259
256
  end
260
257
 
261
258
  should "work with conditions" do
262
- @project1.statuses.find(:first, :name => 'Complete').should == @complete
263
259
  @project1.statuses.first(:name => 'Complete').should == @complete
264
260
  end
265
261
  end
266
262
 
267
263
  context "last" do
268
264
  should "work" do
269
- @project1.statuses.find(:last, :order => "position asc").should == @complete
270
265
  @project1.statuses.last(:order => "position asc").should == @complete
271
266
  end
272
267
 
273
268
  should "work with conditions" do
274
- @project1.statuses.find(:last, :order => 'position', :name => 'New').should == @brand_new
275
269
  @project1.statuses.last(:order => 'position', :name => 'New').should == @brand_new
276
270
  end
277
271
  end
@@ -295,9 +289,9 @@ class ManyDocumentsProxyTest < Test::Unit::TestCase
295
289
  end
296
290
 
297
291
  should "not work for ids not in association" do
298
- lambda {
292
+ assert_raises(MongoMapper::DocumentNotFound) do
299
293
  @project1.statuses.find!(@brand_new.id, @complete.id, @archived.id)
300
- }.should raise_error(MongoMapper::DocumentNotFound)
294
+ end
301
295
  end
302
296
  end
303
297
 
@@ -21,30 +21,50 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
21
21
 
22
22
  should "be able to replace the association" do
23
23
  catalog = Catalog.new
24
- catalog.medias = [Video.new("file" => "video.mpg", "length" => 3600)]
24
+ catalog.medias = [Video.new('file' => 'video.mpg', 'length' => 3600)]
25
25
  catalog.save.should be_true
26
26
 
27
27
  catalog = catalog.reload
28
28
  catalog.medias.size.should == 1
29
- catalog.medias[0].file.should == "video.mpg"
29
+ catalog.medias[0].file.should == 'video.mpg'
30
+ catalog.medias[0].new?.should == false
30
31
  end
31
-
32
+
33
+ context "count" do
34
+ should "default to 0" do
35
+ Catalog.new.medias.count.should == 0
36
+ end
37
+
38
+ should 'return correct count if any are embedded' do
39
+ catalog = Catalog.new
40
+ catalog.medias = [
41
+ Video.new('file' => 'video.mpg', 'length' => 3600),
42
+ Music.new('file' => 'music.mp3', 'bitrate' => '128kbps'),
43
+ Image.new('file' => 'image.png', 'width' => 800, 'height' => 600)
44
+ ]
45
+ catalog.medias.count.should == 3
46
+ catalog.save.should be_true
47
+ catalog.reload
48
+ catalog.medias.count.should == 3
49
+ end
50
+ end
51
+
32
52
  should "store different associations" do
33
53
  catalog = Catalog.new
34
54
  catalog.medias = [
35
- Video.new("file" => "video.mpg", "length" => 3600),
36
- Music.new("file" => "music.mp3", "bitrate" => "128kbps"),
37
- Image.new("file" => "image.png", "width" => 800, "height" => 600)
55
+ Video.new('file' => 'video.mpg', 'length' => 3600),
56
+ Music.new('file' => 'music.mp3', 'bitrate' => '128kbps'),
57
+ Image.new('file' => 'image.png', 'width' => 800, 'height' => 600)
38
58
  ]
39
59
  catalog.save.should be_true
40
60
 
41
61
  catalog = catalog.reload
42
62
  catalog.medias.size.should == 3
43
- catalog.medias[0].file.should == "video.mpg"
63
+ catalog.medias[0].file.should == 'video.mpg'
44
64
  catalog.medias[0].length.should == 3600
45
- catalog.medias[1].file.should == "music.mp3"
65
+ catalog.medias[1].file.should == 'music.mp3'
46
66
  catalog.medias[1].bitrate.should == "128kbps"
47
- catalog.medias[2].file.should == "image.png"
67
+ catalog.medias[2].file.should == 'image.png'
48
68
  catalog.medias[2].width.should == 800
49
69
  catalog.medias[2].height.should == 600
50
70
  end
@@ -52,38 +72,38 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
52
72
  context "With modularized models" do
53
73
  should "set associations correctly" do
54
74
  fleet_attributes = {
55
- "name" => "My Fleet",
56
- "transports" => [
57
- {"_type" => "TrModels::Ambulance", "license_plate" => "GGG123", "icu" => true},
58
- {"_type" => "TrModels::Car", "license_plate" => "ABC123", "model" => "VW Golf", "year" => 2001},
59
- {"_type" => "TrModels::Car", "license_plate" => "DEF123", "model" => "Honda Accord", "year" => 2008},
75
+ 'name' => 'My Fleet',
76
+ 'transports' => [
77
+ {'_type' => 'TrModels::Ambulance', 'license_plate' => 'GGG123', 'icu' => true},
78
+ {'_type' => 'TrModels::Car', 'license_plate' => 'ABC123', 'model' => 'VW Golf', 'year' => 2001},
79
+ {'_type' => 'TrModels::Car', 'license_plate' => 'DEF123', 'model' => 'Honda Accord', 'year' => 2008},
60
80
  ]
61
81
  }
62
82
 
63
83
  fleet = TrModels::Fleet.new(fleet_attributes)
64
84
  fleet.transports.size.should == 3
65
85
  fleet.transports[0].class.should == TrModels::Ambulance
66
- fleet.transports[0].license_plate.should == "GGG123"
86
+ fleet.transports[0].license_plate.should == 'GGG123'
67
87
  fleet.transports[0].icu.should be_true
68
88
  fleet.transports[1].class.should == TrModels::Car
69
- fleet.transports[1].license_plate.should == "ABC123"
70
- fleet.transports[1].model.should == "VW Golf"
89
+ fleet.transports[1].license_plate.should == 'ABC123'
90
+ fleet.transports[1].model.should == 'VW Golf'
71
91
  fleet.transports[1].year.should == 2001
72
92
  fleet.transports[2].class.should == TrModels::Car
73
- fleet.transports[2].license_plate.should == "DEF123"
74
- fleet.transports[2].model.should == "Honda Accord"
93
+ fleet.transports[2].license_plate.should == 'DEF123'
94
+ fleet.transports[2].model.should == 'Honda Accord'
75
95
  fleet.transports[2].year.should == 2008
76
96
  fleet.save.should be_true
77
97
 
78
98
  fleet = fleet.reload
79
99
  fleet.transports.size.should == 3
80
- fleet.transports[0].license_plate.should == "GGG123"
100
+ fleet.transports[0].license_plate.should == 'GGG123'
81
101
  fleet.transports[0].icu.should be_true
82
- fleet.transports[1].license_plate.should == "ABC123"
83
- fleet.transports[1].model.should == "VW Golf"
102
+ fleet.transports[1].license_plate.should == 'ABC123'
103
+ fleet.transports[1].model.should == 'VW Golf'
84
104
  fleet.transports[1].year.should == 2001
85
- fleet.transports[2].license_plate.should == "DEF123"
86
- fleet.transports[2].model.should == "Honda Accord"
105
+ fleet.transports[2].license_plate.should == 'DEF123'
106
+ fleet.transports[2].model.should == 'Honda Accord'
87
107
  fleet.transports[2].year.should == 2008
88
108
  end
89
109
 
@@ -101,31 +121,31 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
101
121
 
102
122
  should "be able to replace the association" do
103
123
  fleet = TrModels::Fleet.new
104
- fleet.transports = [TrModels::Car.new("license_plate" => "DCU2013", "model" => "Honda Civic")]
124
+ fleet.transports = [TrModels::Car.new('license_plate' => 'DCU2013', 'model' => 'Honda Civic')]
105
125
  fleet.save.should be_true
106
126
 
107
127
  fleet = fleet.reload
108
128
  fleet.transports.size.should == 1
109
- fleet.transports[0].license_plate.should == "DCU2013"
129
+ fleet.transports[0].license_plate.should == 'DCU2013'
110
130
  end
111
131
 
112
132
  should "store different associations" do
113
133
  fleet = TrModels::Fleet.new
114
134
  fleet.transports = [
115
- TrModels::Car.new("license_plate" => "ABC1223", "model" => "Honda Civic", "year" => 2003),
116
- TrModels::Bus.new("license_plate" => "XYZ9090", "max_passengers" => 51),
117
- TrModels::Ambulance.new("license_plate" => "HDD3030", "icu" => true)
135
+ TrModels::Car.new('license_plate' => 'ABC1223', 'model' => 'Honda Civic', 'year' => 2003),
136
+ TrModels::Bus.new('license_plate' => 'XYZ9090', 'max_passengers' => 51),
137
+ TrModels::Ambulance.new('license_plate' => 'HDD3030', 'icu' => true)
118
138
  ]
119
139
  fleet.save.should be_true
120
140
 
121
141
  fleet = fleet.reload
122
142
  fleet.transports.size.should == 3
123
- fleet.transports[0].license_plate.should == "ABC1223"
124
- fleet.transports[0].model.should == "Honda Civic"
143
+ fleet.transports[0].license_plate.should == 'ABC1223'
144
+ fleet.transports[0].model.should == 'Honda Civic'
125
145
  fleet.transports[0].year.should == 2003
126
- fleet.transports[1].license_plate.should == "XYZ9090"
146
+ fleet.transports[1].license_plate.should == 'XYZ9090'
127
147
  fleet.transports[1].max_passengers.should == 51
128
- fleet.transports[2].license_plate.should == "HDD3030"
148
+ fleet.transports[2].license_plate.should == 'HDD3030'
129
149
  fleet.transports[2].icu.should == true
130
150
  end
131
151
  end
@@ -134,9 +154,9 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
134
154
  should "work using a block passed to many" do
135
155
  catalog = Catalog.new
136
156
  medias = catalog.medias = [
137
- Video.new("file" => "video.mpg", "length" => 3600, :visible => true),
138
- Music.new("file" => "music.mp3", "bitrate" => "128kbps", :visible => true),
139
- Image.new("file" => "image.png", "width" => 800, "height" => 600, :visible => false)
157
+ Video.new('file' => 'video.mpg', 'length' => 3600, :visible => true),
158
+ Music.new('file' => 'music.mp3', 'bitrate' => '128kbps', :visible => true),
159
+ Image.new('file' => 'image.png', 'width' => 800, 'height' => 600, :visible => false)
140
160
  ]
141
161
  catalog.save
142
162
  catalog.medias.visible.should == [medias[0], medias[1]]
@@ -145,9 +165,9 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
145
165
  should "work using many's :extend option" do
146
166
  fleet = TrModels::Fleet.new
147
167
  transports = fleet.transports = [
148
- TrModels::Car.new("license_plate" => "ABC1223", "model" => "Honda Civic", "year" => 2003, :purchased_on => 2.years.ago.to_date),
149
- TrModels::Bus.new("license_plate" => "XYZ9090", "max_passengers" => 51, :purchased_on => 3.years.ago.to_date),
150
- TrModels::Ambulance.new("license_plate" => "HDD3030", "icu" => true, :purchased_on => 1.year.ago.to_date)
168
+ TrModels::Car.new('license_plate' => 'ABC1223', 'model' => 'Honda Civic', 'year' => 2003, :purchased_on => 2.years.ago.to_date),
169
+ TrModels::Bus.new('license_plate' => 'XYZ9090', 'max_passengers' => 51, :purchased_on => 3.years.ago.to_date),
170
+ TrModels::Ambulance.new('license_plate' => 'HDD3030', 'icu' => true, :purchased_on => 1.year.ago.to_date)
151
171
  ]
152
172
  fleet.save
153
173
  fleet.transports.to_be_replaced.should == [transports[1]]
@@ -3,126 +3,153 @@ require 'models'
3
3
 
4
4
  class ManyEmbeddedProxyTest < Test::Unit::TestCase
5
5
  def setup
6
- Project.collection.remove
7
- RealPerson.collection.remove
6
+ @comment_class = EDoc do
7
+ key :name, String
8
+ key :body, String
9
+ end
10
+ @post_class = Doc do
11
+ key :title, String
12
+ end
13
+ @post_class.many :comments, :class => @comment_class
14
+
15
+ @pet_class = EDoc do
16
+ key :name, String
17
+ end
18
+ @pet_class.embedded_in :person
19
+ @person_class = EDoc do
20
+ key :name, String
21
+ end
22
+ @person_class.key :child, @person_class
23
+ @person_class.many :pets, :class => @pet_class
24
+
25
+ @owner_class = Doc do
26
+ key :name, String
27
+ end
28
+ @owner_class.many :pets, :class => @pet_class
8
29
  end
9
30
 
10
31
  should "default reader to empty array" do
11
- Project.new.addresses.should == []
32
+ @post_class.new.comments.should == []
12
33
  end
13
34
 
14
35
  should "allow adding to association like it was an array" do
15
- project = Project.new
16
- project.addresses << Address.new
17
- project.addresses.push Address.new
18
- project.addresses.size.should == 2
36
+ post = @post_class.new
37
+ post.comments << @comment_class.new
38
+ post.comments.push @comment_class.new
39
+ post.comments.size.should == 2
19
40
  end
20
41
 
21
42
  should "be embedded in document on save" do
22
- sb = Address.new(:city => 'South Bend', :state => 'IN')
23
- chi = Address.new(:city => 'Chicago', :state => 'IL')
24
- project = Project.new
25
- project.addresses << sb
26
- project.addresses << chi
27
- project.save
43
+ frank = @comment_class.new(:name => 'Frank', :body => 'Hi!')
44
+ bill = @comment_class.new(:name => 'Bill', :body => 'Hi!')
45
+ post = @post_class.new
46
+ post.comments << frank
47
+ post.comments << bill
48
+ post.save
28
49
 
29
- project.reload
30
- project.addresses.size.should == 2
31
- project.addresses[0].should == sb
32
- project.addresses[1].should == chi
50
+ post.reload
51
+ post.comments.size.should == 2
52
+ post.comments[0].should == frank
53
+ post.comments[0].new?.should == false
54
+ post.comments[1].should == bill
55
+ post.comments[1].new?.should == false
33
56
  end
34
57
 
35
58
  should "allow embedding arbitrarily deep" do
36
- @document = Class.new do
37
- include MongoMapper::Document
38
- set_collection_name 'test'
39
- key :person, Person
40
- end
41
- @document.collection.remove
59
+ @klass = Doc()
60
+ @klass.key :person, @person_class
42
61
 
43
- meg = Person.new(:name => "Meg")
44
- meg.child = Person.new(:name => "Steve")
45
- meg.child.child = Person.new(:name => "Linda")
62
+ meg = @person_class.new(:name => 'Meg')
63
+ meg.child = @person_class.new(:name => 'Steve')
64
+ meg.child.child = @person_class.new(:name => 'Linda')
46
65
 
47
- doc = @document.new(:person => meg)
66
+ doc = @klass.new(:person => meg)
48
67
  doc.save
49
-
50
68
  doc.reload
69
+
51
70
  doc.person.name.should == 'Meg'
52
71
  doc.person.child.name.should == 'Steve'
53
72
  doc.person.child.child.name.should == 'Linda'
54
73
  end
55
74
 
56
- should "allow assignment of 'many' embedded documents using a hash" do
75
+ should "allow assignment of many embedded documents using a hash" do
57
76
  person_attributes = {
58
- "name" => "Mr. Pet Lover",
59
- "pets" => [
60
- {"name" => "Jimmy", "species" => "Cocker Spainel"},
61
- {"name" => "Sasha", "species" => "Siberian Husky"},
77
+ 'name' => 'Mr. Pet Lover',
78
+ 'pets' => [
79
+ {'name' => 'Jimmy', 'species' => 'Cocker Spainel'},
80
+ {'name' => 'Sasha', 'species' => 'Siberian Husky'},
62
81
  ]
63
82
  }
64
83
 
65
- pet_lover = RealPerson.new(person_attributes)
66
- pet_lover.name.should == "Mr. Pet Lover"
67
- pet_lover.pets[0].name.should == "Jimmy"
68
- pet_lover.pets[0].species.should == "Cocker Spainel"
69
- pet_lover.pets[1].name.should == "Sasha"
70
- pet_lover.pets[1].species.should == "Siberian Husky"
71
- pet_lover.save.should be_true
72
-
73
- pet_lover.reload
74
- pet_lover.name.should == "Mr. Pet Lover"
75
- pet_lover.pets[0].name.should == "Jimmy"
76
- pet_lover.pets[0].species.should == "Cocker Spainel"
77
- pet_lover.pets[1].name.should == "Sasha"
78
- pet_lover.pets[1].species.should == "Siberian Husky"
84
+ owner = @owner_class.new(person_attributes)
85
+ owner.name.should == 'Mr. Pet Lover'
86
+ owner.pets[0].name.should == 'Jimmy'
87
+ owner.pets[0].species.should == 'Cocker Spainel'
88
+ owner.pets[1].name.should == 'Sasha'
89
+ owner.pets[1].species.should == 'Siberian Husky'
90
+
91
+ owner.save.should be_true
92
+ owner.reload
93
+
94
+ owner.name.should == 'Mr. Pet Lover'
95
+ owner.pets[0].name.should == 'Jimmy'
96
+ owner.pets[0].species.should == 'Cocker Spainel'
97
+ owner.pets[1].name.should == 'Sasha'
98
+ owner.pets[1].species.should == 'Siberian Husky'
79
99
  end
80
100
 
81
101
  context "embedding many embedded documents" do
82
102
  setup do
83
- @document = Class.new do
84
- include MongoMapper::Document
85
- set_collection_name 'test'
86
- many :people
87
- end
88
- @document.collection.remove
103
+ @klass = Doc()
104
+ @klass.many :people, :class => @person_class
89
105
  end
90
106
 
91
107
  should "persist all embedded documents" do
92
- meg = Person.new(:name => "Meg")
93
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
94
- koda = Pet.new(:name => "Koda", :species => "Dog")
95
-
96
- doc = @document.new
97
- meg.pets << sparky
98
- meg.pets << koda
108
+ meg = @person_class.new(:name => 'Meg', :pets => [
109
+ @pet_class.new(:name => 'Sparky', :species => 'Dog'),
110
+ @pet_class.new(:name => 'Koda', :species => 'Dog')
111
+ ])
112
+
113
+ doc = @klass.new
99
114
  doc.people << meg
100
115
  doc.save
101
-
102
116
  doc.reload
103
- doc.people.first.name.should == "Meg"
117
+
118
+ doc.people.first.name.should == 'Meg'
104
119
  doc.people.first.pets.should_not == []
105
- doc.people.first.pets.first.name.should == "Sparky"
106
- doc.people.first.pets.first.species.should == "Dog"
107
- doc.people.first.pets[1].name.should == "Koda"
108
- doc.people.first.pets[1].species.should == "Dog"
120
+ doc.people.first.pets.first.name.should == 'Sparky'
121
+ doc.people.first.pets.first.species.should == 'Dog'
122
+ doc.people.first.pets[1].name.should == 'Koda'
123
+ doc.people.first.pets[1].species.should == 'Dog'
109
124
  end
110
125
 
111
126
  should "create a reference to the root document for all embedded documents before save" do
112
- meg = Person.new(:name => "Meg")
113
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
114
- doc = @document.new
127
+ doc = @klass.new
128
+ meg = @person_class.new(:name => 'Meg')
129
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
130
+
115
131
  doc.people << meg
116
- meg.pets << sparky
132
+ meg.pets << pet
117
133
 
118
134
  doc.people.first._root_document.should == doc
119
135
  doc.people.first.pets.first._root_document.should == doc
120
136
  end
137
+ should "create a reference to the owning document for all embedded documents before save" do
138
+ doc = @klass.new
139
+ meg = @person_class.new(:name => 'Meg')
140
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
141
+
142
+ doc.people << meg
143
+ meg.pets << pet
144
+
145
+ doc.people.first._parent_document.should == doc
146
+ doc.people.first.pets.first._parent_document.should == doc.people.first
147
+ end
121
148
 
122
149
  should "create a reference to the root document for all embedded documents" do
123
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
124
- meg = Person.new(:name => "Meg", :pets => [sparky])
125
- doc = @document.new
150
+ sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
151
+ meg = @person_class.new(:name => 'Meg', :pets => [sparky])
152
+ doc = @klass.new
126
153
  doc.people << meg
127
154
  doc.save
128
155
 
@@ -130,32 +157,69 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
130
157
  doc.people.first._root_document.should == doc
131
158
  doc.people.first.pets.first._root_document.should == doc
132
159
  end
160
+ should "create a reference to the owning document for all embedded documents" do
161
+ doc = @klass.new
162
+ meg = @person_class.new(:name => 'Meg')
163
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
164
+
165
+ doc.people << meg
166
+ meg.pets << pet
167
+ doc.save
168
+
169
+ doc.reload
170
+ doc.people.first._parent_document.should == doc
171
+ doc.people.first.pets.first._parent_document.should == doc.people.first
172
+ end
173
+
174
+ should "create embedded_in relationship for embedded docs" do
175
+ doc = @klass.new
176
+ meg = @person_class.new(:name => 'Meg')
177
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
178
+
179
+ doc.people << meg
180
+ meg.pets << pet
181
+ doc.save
182
+
183
+ doc.reload
184
+ doc.people.first.pets.first.person.should == doc.people.first
185
+ end
133
186
  end
134
187
 
135
188
  should "allow finding by id" do
136
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
137
- meg = Person.new(:name => "Meg", :pets => [sparky])
189
+ sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
190
+ meg = @owner_class.create(:name => 'Meg', :pets => [sparky])
138
191
 
139
192
  meg.pets.find(sparky._id).should == sparky # oid
140
193
  meg.pets.find(sparky.id.to_s).should == sparky # string
141
194
  end
142
195
 
196
+ context "count" do
197
+ should "default to 0" do
198
+ @owner_class.new.pets.count.should == 0
199
+ end
200
+
201
+ should "return correct count if any are embedded" do
202
+ owner = @owner_class.new(:name => 'Meg')
203
+ owner.pets = [@pet_class.new, @pet_class.new]
204
+ owner.pets.count.should == 2
205
+ owner.save
206
+ owner.reload
207
+ owner.pets.count.should == 2
208
+ end
209
+ end
210
+
143
211
  context "extending the association" do
144
212
  setup do
145
- @address_class = Class.new do
146
- include MongoMapper::EmbeddedDocument
213
+ @address_class = EDoc do
147
214
  key :address, String
148
215
  key :city, String
149
216
  key :state, String
150
217
  key :zip, Integer
151
218
  end
152
219
 
153
- @project_class = Class.new do
154
- include MongoMapper::Document
220
+ @project_class = Doc do
155
221
  key :name, String
156
222
  end
157
-
158
- @project_class.collection.remove
159
223
  end
160
224
 
161
225
  should "work using a block passed to many" do