mongo_mapper-unstable 2010.1.6 → 2010.1.12

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 (86) hide show
  1. data/VERSION +1 -1
  2. data/lib/mongo_mapper/descendant_appends.rb +44 -0
  3. data/lib/mongo_mapper/document.rb +54 -98
  4. data/lib/mongo_mapper/embedded_document.rb +28 -348
  5. data/lib/mongo_mapper/finder_options.rb +15 -33
  6. data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
  7. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +28 -0
  8. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +23 -0
  9. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  10. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +49 -0
  11. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  12. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  13. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  14. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  15. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  16. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  17. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +66 -0
  18. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  19. data/lib/mongo_mapper/plugins/associations.rb +104 -0
  20. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  21. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  22. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  23. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  24. data/lib/mongo_mapper/plugins/equality.rb +11 -0
  25. data/lib/mongo_mapper/plugins/identity_map.rb +66 -0
  26. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  27. data/lib/mongo_mapper/plugins/keys.rb +295 -0
  28. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  29. data/lib/mongo_mapper/plugins/pagination.rb +85 -0
  30. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  31. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  32. data/lib/mongo_mapper/plugins/validations.rb +48 -0
  33. data/lib/mongo_mapper/plugins.rb +19 -0
  34. data/lib/mongo_mapper/support.rb +36 -15
  35. data/lib/mongo_mapper.rb +23 -22
  36. data/performance/read_write.rb +52 -0
  37. data/specs.watchr +23 -2
  38. data/test/functional/associations/test_belongs_to_proxy.rb +1 -1
  39. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +58 -39
  40. data/test/functional/associations/test_many_embedded_proxy.rb +103 -69
  41. data/test/functional/test_dirty.rb +1 -1
  42. data/test/functional/test_document.rb +25 -25
  43. data/test/functional/test_embedded_document.rb +66 -63
  44. data/test/functional/test_identity_map.rb +233 -0
  45. data/test/functional/test_modifiers.rb +14 -0
  46. data/test/functional/test_string_id_compatibility.rb +4 -4
  47. data/test/functional/test_validations.rb +13 -0
  48. data/test/models.rb +0 -39
  49. data/test/test_helper.rb +8 -2
  50. data/test/unit/associations/test_base.rb +1 -1
  51. data/test/unit/associations/test_proxy.rb +3 -3
  52. data/test/unit/test_descendant_appends.rb +71 -0
  53. data/test/unit/test_document.rb +35 -46
  54. data/test/unit/test_embedded_document.rb +218 -271
  55. data/test/unit/{test_key.rb → test_keys.rb} +0 -0
  56. data/test/unit/test_pagination.rb +10 -2
  57. data/test/unit/test_plugins.rb +42 -0
  58. data/test/unit/test_rails.rb +123 -0
  59. data/test/unit/{test_serializations.rb → test_serialization.rb} +0 -0
  60. data/test/unit/test_support.rb +10 -6
  61. data/test/unit/test_time_zones.rb +2 -2
  62. metadata +44 -31
  63. data/lib/mongo_mapper/associations/base.rb +0 -119
  64. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  65. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  66. data/lib/mongo_mapper/associations/collection.rb +0 -19
  67. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  68. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  69. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  70. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  71. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  72. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  73. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  74. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  75. data/lib/mongo_mapper/associations.rb +0 -78
  76. data/lib/mongo_mapper/callbacks.rb +0 -61
  77. data/lib/mongo_mapper/dirty.rb +0 -117
  78. data/lib/mongo_mapper/key.rb +0 -36
  79. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  80. data/lib/mongo_mapper/pagination.rb +0 -66
  81. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  82. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  83. data/lib/mongo_mapper/serialization.rb +0 -54
  84. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  85. data/lib/mongo_mapper/validations.rb +0 -39
  86. data/test/functional/test_rails_compatibility.rb +0 -25
data/lib/mongo_mapper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'set'
2
+
1
3
  # if Gem is defined i'll assume you are using rubygems and lock specific versions
2
4
  # call me crazy but a plain old require will just get the latest version you have installed
3
5
  # so i want to make sure that if you are using gems you do in fact have the correct versions
@@ -98,29 +100,28 @@ module MongoMapper
98
100
  end
99
101
  end
100
102
 
101
- require 'mongo_mapper/support'
102
- require 'mongo_mapper/callbacks'
103
103
  require 'mongo_mapper/finder_options'
104
- require 'mongo_mapper/dirty'
104
+ require 'mongo_mapper/support'
105
+ require 'mongo_mapper/descendant_appends'
106
+
105
107
  require 'mongo_mapper/dynamic_finder'
106
108
  require 'mongo_mapper/key'
107
- require 'mongo_mapper/pagination'
108
- require 'mongo_mapper/serialization'
109
- require 'mongo_mapper/validations'
110
- require 'mongo_mapper/rails_compatibility/document'
111
- require 'mongo_mapper/rails_compatibility/embedded_document'
109
+
110
+ require 'mongo_mapper/plugins'
111
+ require 'mongo_mapper/plugins/associations'
112
+ require 'mongo_mapper/plugins/callbacks'
113
+ require 'mongo_mapper/plugins/clone'
114
+ require 'mongo_mapper/plugins/descendants'
115
+ require 'mongo_mapper/plugins/dirty'
116
+ require 'mongo_mapper/plugins/equality'
117
+ require 'mongo_mapper/plugins/identity_map'
118
+ require 'mongo_mapper/plugins/inspect'
119
+ require 'mongo_mapper/plugins/keys'
120
+ require 'mongo_mapper/plugins/logger'
121
+ require 'mongo_mapper/plugins/pagination'
122
+ require 'mongo_mapper/plugins/rails'
123
+ require 'mongo_mapper/plugins/serialization'
124
+ require 'mongo_mapper/plugins/validations'
125
+
112
126
  require 'mongo_mapper/embedded_document'
113
- require 'mongo_mapper/document'
114
- require 'mongo_mapper/associations'
115
- require 'mongo_mapper/associations/base'
116
- require 'mongo_mapper/associations/proxy'
117
- require 'mongo_mapper/associations/collection'
118
- require 'mongo_mapper/associations/many_documents_proxy'
119
- require 'mongo_mapper/associations/belongs_to_proxy'
120
- require 'mongo_mapper/associations/belongs_to_polymorphic_proxy'
121
- require 'mongo_mapper/associations/many_polymorphic_proxy'
122
- require 'mongo_mapper/associations/many_embedded_proxy'
123
- require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
124
- require 'mongo_mapper/associations/many_documents_as_proxy'
125
- require 'mongo_mapper/associations/one_proxy'
126
- require 'mongo_mapper/associations/in_array_proxy'
127
+ require 'mongo_mapper/document'
@@ -0,0 +1,52 @@
1
+ # The purpose of this is to check finding, initializing,
2
+ # and creating objects (typecasting times/dates and booleans).
3
+
4
+ require 'pp'
5
+ require 'benchmark'
6
+ require 'rubygems'
7
+
8
+ # to test with slow version just do this:
9
+ # gem 'mongo_mapper', '0.6.10'
10
+ # and comment out this:
11
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
12
+
13
+ require 'mongo_mapper'
14
+
15
+ MongoMapper.database = 'testing'
16
+
17
+ class Foo
18
+ include MongoMapper::Document
19
+ key :approved, Boolean
20
+ key :count, Integer
21
+ key :approved_at, Time
22
+ key :expire_on, Date
23
+ timestamps!
24
+ end
25
+ Foo.collection.remove
26
+
27
+ Benchmark.bm(5) do |x|
28
+ ids = []
29
+ x.report("write") do
30
+ 1000.times { |i| ids << Foo.create(:count => 0, :approved => true, :approved_at => Time.now, :expire_on => Date.today).id }
31
+ end
32
+
33
+ x.report("read ") do
34
+ ids.each { |id| Foo.first(:id => id) }
35
+ end
36
+ end
37
+
38
+ # I was get something like this on my puny macbook air:
39
+ # user system total real
40
+ # write 4.810000 0.090000 4.900000 ( 5.039949)
41
+ # read 2.730000 0.070000 2.800000 ( 2.990749)
42
+ #
43
+ #
44
+ # After these commits:
45
+ #
46
+ # * http://github.com/jnunemaker/mongomapper/commit/e5091fa140d5fae2721017b53027092233694ee5
47
+ # * http://github.com/jnunemaker/mongomapper/commit/c22bbde4fa1cfbc310d79cb0e50203310ffb03d1
48
+ #
49
+ # I'm now getting something like this:
50
+ # user system total real
51
+ # write 1.660000 0.050000 1.710000 ( 1.752676)
52
+ # read 1.060000 0.050000 1.110000 ( 1.263429)
data/specs.watchr CHANGED
@@ -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
@@ -72,7 +72,7 @@ class BelongsToProxyTest < Test::Unit::TestCase
72
72
  setup do
73
73
  Property.key :thing_id, ObjectId
74
74
  Property.belongs_to :thing, :dependent => :destroy
75
- Thing.has_many :properties
75
+ Thing.many :properties
76
76
 
77
77
  @thing = Thing.create(:name => "Tree")
78
78
  @property1 = Property.create
@@ -21,30 +21,49 @@ 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
30
  end
31
-
31
+
32
+ context "count" do
33
+ should "default to 0" do
34
+ Catalog.new.medias.count.should == 0
35
+ end
36
+
37
+ should 'return correct count if any are embedded' do
38
+ catalog = Catalog.new
39
+ catalog.medias = [
40
+ Video.new('file' => 'video.mpg', 'length' => 3600),
41
+ Music.new('file' => 'music.mp3', 'bitrate' => '128kbps'),
42
+ Image.new('file' => 'image.png', 'width' => 800, 'height' => 600)
43
+ ]
44
+ catalog.medias.count.should == 3
45
+ catalog.save.should be_true
46
+ catalog.reload
47
+ catalog.medias.count.should == 3
48
+ end
49
+ end
50
+
32
51
  should "store different associations" do
33
52
  catalog = Catalog.new
34
53
  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)
54
+ Video.new('file' => 'video.mpg', 'length' => 3600),
55
+ Music.new('file' => 'music.mp3', 'bitrate' => '128kbps'),
56
+ Image.new('file' => 'image.png', 'width' => 800, 'height' => 600)
38
57
  ]
39
58
  catalog.save.should be_true
40
59
 
41
60
  catalog = catalog.reload
42
61
  catalog.medias.size.should == 3
43
- catalog.medias[0].file.should == "video.mpg"
62
+ catalog.medias[0].file.should == 'video.mpg'
44
63
  catalog.medias[0].length.should == 3600
45
- catalog.medias[1].file.should == "music.mp3"
64
+ catalog.medias[1].file.should == 'music.mp3'
46
65
  catalog.medias[1].bitrate.should == "128kbps"
47
- catalog.medias[2].file.should == "image.png"
66
+ catalog.medias[2].file.should == 'image.png'
48
67
  catalog.medias[2].width.should == 800
49
68
  catalog.medias[2].height.should == 600
50
69
  end
@@ -52,38 +71,38 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
52
71
  context "With modularized models" do
53
72
  should "set associations correctly" do
54
73
  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},
74
+ 'name' => 'My Fleet',
75
+ 'transports' => [
76
+ {'_type' => 'TrModels::Ambulance', 'license_plate' => 'GGG123', 'icu' => true},
77
+ {'_type' => 'TrModels::Car', 'license_plate' => 'ABC123', 'model' => 'VW Golf', 'year' => 2001},
78
+ {'_type' => 'TrModels::Car', 'license_plate' => 'DEF123', 'model' => 'Honda Accord', 'year' => 2008},
60
79
  ]
61
80
  }
62
81
 
63
82
  fleet = TrModels::Fleet.new(fleet_attributes)
64
83
  fleet.transports.size.should == 3
65
84
  fleet.transports[0].class.should == TrModels::Ambulance
66
- fleet.transports[0].license_plate.should == "GGG123"
85
+ fleet.transports[0].license_plate.should == 'GGG123'
67
86
  fleet.transports[0].icu.should be_true
68
87
  fleet.transports[1].class.should == TrModels::Car
69
- fleet.transports[1].license_plate.should == "ABC123"
70
- fleet.transports[1].model.should == "VW Golf"
88
+ fleet.transports[1].license_plate.should == 'ABC123'
89
+ fleet.transports[1].model.should == 'VW Golf'
71
90
  fleet.transports[1].year.should == 2001
72
91
  fleet.transports[2].class.should == TrModels::Car
73
- fleet.transports[2].license_plate.should == "DEF123"
74
- fleet.transports[2].model.should == "Honda Accord"
92
+ fleet.transports[2].license_plate.should == 'DEF123'
93
+ fleet.transports[2].model.should == 'Honda Accord'
75
94
  fleet.transports[2].year.should == 2008
76
95
  fleet.save.should be_true
77
96
 
78
97
  fleet = fleet.reload
79
98
  fleet.transports.size.should == 3
80
- fleet.transports[0].license_plate.should == "GGG123"
99
+ fleet.transports[0].license_plate.should == 'GGG123'
81
100
  fleet.transports[0].icu.should be_true
82
- fleet.transports[1].license_plate.should == "ABC123"
83
- fleet.transports[1].model.should == "VW Golf"
101
+ fleet.transports[1].license_plate.should == 'ABC123'
102
+ fleet.transports[1].model.should == 'VW Golf'
84
103
  fleet.transports[1].year.should == 2001
85
- fleet.transports[2].license_plate.should == "DEF123"
86
- fleet.transports[2].model.should == "Honda Accord"
104
+ fleet.transports[2].license_plate.should == 'DEF123'
105
+ fleet.transports[2].model.should == 'Honda Accord'
87
106
  fleet.transports[2].year.should == 2008
88
107
  end
89
108
 
@@ -101,31 +120,31 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
101
120
 
102
121
  should "be able to replace the association" do
103
122
  fleet = TrModels::Fleet.new
104
- fleet.transports = [TrModels::Car.new("license_plate" => "DCU2013", "model" => "Honda Civic")]
123
+ fleet.transports = [TrModels::Car.new('license_plate' => 'DCU2013', 'model' => 'Honda Civic')]
105
124
  fleet.save.should be_true
106
125
 
107
126
  fleet = fleet.reload
108
127
  fleet.transports.size.should == 1
109
- fleet.transports[0].license_plate.should == "DCU2013"
128
+ fleet.transports[0].license_plate.should == 'DCU2013'
110
129
  end
111
130
 
112
131
  should "store different associations" do
113
132
  fleet = TrModels::Fleet.new
114
133
  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)
134
+ TrModels::Car.new('license_plate' => 'ABC1223', 'model' => 'Honda Civic', 'year' => 2003),
135
+ TrModels::Bus.new('license_plate' => 'XYZ9090', 'max_passengers' => 51),
136
+ TrModels::Ambulance.new('license_plate' => 'HDD3030', 'icu' => true)
118
137
  ]
119
138
  fleet.save.should be_true
120
139
 
121
140
  fleet = fleet.reload
122
141
  fleet.transports.size.should == 3
123
- fleet.transports[0].license_plate.should == "ABC1223"
124
- fleet.transports[0].model.should == "Honda Civic"
142
+ fleet.transports[0].license_plate.should == 'ABC1223'
143
+ fleet.transports[0].model.should == 'Honda Civic'
125
144
  fleet.transports[0].year.should == 2003
126
- fleet.transports[1].license_plate.should == "XYZ9090"
145
+ fleet.transports[1].license_plate.should == 'XYZ9090'
127
146
  fleet.transports[1].max_passengers.should == 51
128
- fleet.transports[2].license_plate.should == "HDD3030"
147
+ fleet.transports[2].license_plate.should == 'HDD3030'
129
148
  fleet.transports[2].icu.should == true
130
149
  end
131
150
  end
@@ -134,9 +153,9 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
134
153
  should "work using a block passed to many" do
135
154
  catalog = Catalog.new
136
155
  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)
156
+ Video.new('file' => 'video.mpg', 'length' => 3600, :visible => true),
157
+ Music.new('file' => 'music.mp3', 'bitrate' => '128kbps', :visible => true),
158
+ Image.new('file' => 'image.png', 'width' => 800, 'height' => 600, :visible => false)
140
159
  ]
141
160
  catalog.save
142
161
  catalog.medias.visible.should == [medias[0], medias[1]]
@@ -145,9 +164,9 @@ class ManyEmbeddedPolymorphicProxyTest < Test::Unit::TestCase
145
164
  should "work using many's :extend option" do
146
165
  fleet = TrModels::Fleet.new
147
166
  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)
167
+ TrModels::Car.new('license_plate' => 'ABC1223', 'model' => 'Honda Civic', 'year' => 2003, :purchased_on => 2.years.ago.to_date),
168
+ TrModels::Bus.new('license_plate' => 'XYZ9090', 'max_passengers' => 51, :purchased_on => 3.years.ago.to_date),
169
+ TrModels::Ambulance.new('license_plate' => 'HDD3030', 'icu' => true, :purchased_on => 1.year.ago.to_date)
151
170
  ]
152
171
  fleet.save
153
172
  fleet.transports.to_be_replaced.should == [transports[1]]
@@ -3,120 +3,139 @@ 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
+ @person_class = EDoc do
19
+ key :name, String
20
+ end
21
+ @person_class.key :child, @person_class
22
+ @person_class.many :pets, :class => @pet_class
23
+
24
+ @owner_class = Doc do
25
+ key :name, String
26
+ end
27
+ @owner_class.many :pets, :class => @pet_class
8
28
  end
9
29
 
10
30
  should "default reader to empty array" do
11
- Project.new.addresses.should == []
31
+ @post_class.new.comments.should == []
12
32
  end
13
33
 
14
34
  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
35
+ post = @post_class.new
36
+ post.comments << @comment_class.new
37
+ post.comments.push @comment_class.new
38
+ post.comments.size.should == 2
19
39
  end
20
40
 
21
41
  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
42
+ frank = @comment_class.new(:name => 'Frank', :body => 'Hi!')
43
+ bill = @comment_class.new(:name => 'Bill', :body => 'Hi!')
44
+ post = @post_class.new
45
+ post.comments << frank
46
+ post.comments << bill
47
+ post.save
28
48
 
29
- project.reload
30
- project.addresses.size.should == 2
31
- project.addresses[0].should == sb
32
- project.addresses[1].should == chi
49
+ post.reload
50
+ post.comments.size.should == 2
51
+ post.comments[0].should == frank
52
+ post.comments[1].should == bill
33
53
  end
34
54
 
35
55
  should "allow embedding arbitrarily deep" do
36
- @document = Doc do
37
- key :person, Person
38
- end
56
+ @klass = Doc()
57
+ @klass.key :person, @person_class
39
58
 
40
- meg = Person.new(:name => "Meg")
41
- meg.child = Person.new(:name => "Steve")
42
- meg.child.child = Person.new(:name => "Linda")
59
+ meg = @person_class.new(:name => 'Meg')
60
+ meg.child = @person_class.new(:name => 'Steve')
61
+ meg.child.child = @person_class.new(:name => 'Linda')
43
62
 
44
- doc = @document.new(:person => meg)
63
+ doc = @klass.new(:person => meg)
45
64
  doc.save
46
-
47
65
  doc.reload
66
+
48
67
  doc.person.name.should == 'Meg'
49
68
  doc.person.child.name.should == 'Steve'
50
69
  doc.person.child.child.name.should == 'Linda'
51
70
  end
52
71
 
53
- should "allow assignment of 'many' embedded documents using a hash" do
72
+ should "allow assignment of many embedded documents using a hash" do
54
73
  person_attributes = {
55
- "name" => "Mr. Pet Lover",
56
- "pets" => [
57
- {"name" => "Jimmy", "species" => "Cocker Spainel"},
58
- {"name" => "Sasha", "species" => "Siberian Husky"},
74
+ 'name' => 'Mr. Pet Lover',
75
+ 'pets' => [
76
+ {'name' => 'Jimmy', 'species' => 'Cocker Spainel'},
77
+ {'name' => 'Sasha', 'species' => 'Siberian Husky'},
59
78
  ]
60
79
  }
61
80
 
62
- pet_lover = RealPerson.new(person_attributes)
63
- pet_lover.name.should == "Mr. Pet Lover"
64
- pet_lover.pets[0].name.should == "Jimmy"
65
- pet_lover.pets[0].species.should == "Cocker Spainel"
66
- pet_lover.pets[1].name.should == "Sasha"
67
- pet_lover.pets[1].species.should == "Siberian Husky"
68
- pet_lover.save.should be_true
69
-
70
- pet_lover.reload
71
- pet_lover.name.should == "Mr. Pet Lover"
72
- pet_lover.pets[0].name.should == "Jimmy"
73
- pet_lover.pets[0].species.should == "Cocker Spainel"
74
- pet_lover.pets[1].name.should == "Sasha"
75
- pet_lover.pets[1].species.should == "Siberian Husky"
81
+ owner = @owner_class.new(person_attributes)
82
+ owner.name.should == 'Mr. Pet Lover'
83
+ owner.pets[0].name.should == 'Jimmy'
84
+ owner.pets[0].species.should == 'Cocker Spainel'
85
+ owner.pets[1].name.should == 'Sasha'
86
+ owner.pets[1].species.should == 'Siberian Husky'
87
+
88
+ owner.save.should be_true
89
+ owner.reload
90
+
91
+ owner.name.should == 'Mr. Pet Lover'
92
+ owner.pets[0].name.should == 'Jimmy'
93
+ owner.pets[0].species.should == 'Cocker Spainel'
94
+ owner.pets[1].name.should == 'Sasha'
95
+ owner.pets[1].species.should == 'Siberian Husky'
76
96
  end
77
97
 
78
98
  context "embedding many embedded documents" do
79
99
  setup do
80
- @document = Doc do
81
- many :people
82
- end
100
+ @klass = Doc()
101
+ @klass.many :people, :class => @person_class
83
102
  end
84
103
 
85
104
  should "persist all embedded documents" do
86
- meg = Person.new(:name => "Meg")
87
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
88
- koda = Pet.new(:name => "Koda", :species => "Dog")
89
-
90
- doc = @document.new
91
- meg.pets << sparky
92
- meg.pets << koda
105
+ meg = @person_class.new(:name => 'Meg', :pets => [
106
+ @pet_class.new(:name => 'Sparky', :species => 'Dog'),
107
+ @pet_class.new(:name => 'Koda', :species => 'Dog')
108
+ ])
109
+
110
+ doc = @klass.new
93
111
  doc.people << meg
94
112
  doc.save
95
-
96
113
  doc.reload
97
- doc.people.first.name.should == "Meg"
114
+
115
+ doc.people.first.name.should == 'Meg'
98
116
  doc.people.first.pets.should_not == []
99
- doc.people.first.pets.first.name.should == "Sparky"
100
- doc.people.first.pets.first.species.should == "Dog"
101
- doc.people.first.pets[1].name.should == "Koda"
102
- doc.people.first.pets[1].species.should == "Dog"
117
+ doc.people.first.pets.first.name.should == 'Sparky'
118
+ doc.people.first.pets.first.species.should == 'Dog'
119
+ doc.people.first.pets[1].name.should == 'Koda'
120
+ doc.people.first.pets[1].species.should == 'Dog'
103
121
  end
104
122
 
105
123
  should "create a reference to the root document for all embedded documents before save" do
106
- meg = Person.new(:name => "Meg")
107
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
108
- doc = @document.new
124
+ doc = @klass.new
125
+ meg = @person_class.new(:name => 'Meg')
126
+ pet = @pet_class.new(:name => 'Sparky', :species => 'Dog')
127
+
109
128
  doc.people << meg
110
- meg.pets << sparky
129
+ meg.pets << pet
111
130
 
112
131
  doc.people.first._root_document.should == doc
113
132
  doc.people.first.pets.first._root_document.should == doc
114
133
  end
115
134
 
116
135
  should "create a reference to the root document for all embedded documents" do
117
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
118
- meg = Person.new(:name => "Meg", :pets => [sparky])
119
- doc = @document.new
136
+ sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
137
+ meg = @person_class.new(:name => 'Meg', :pets => [sparky])
138
+ doc = @klass.new
120
139
  doc.people << meg
121
140
  doc.save
122
141
 
@@ -127,13 +146,28 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
127
146
  end
128
147
 
129
148
  should "allow finding by id" do
130
- sparky = Pet.new(:name => "Sparky", :species => "Dog")
131
- meg = Person.new(:name => "Meg", :pets => [sparky])
149
+ sparky = @pet_class.new(:name => 'Sparky', :species => 'Dog')
150
+ meg = @owner_class.create(:name => 'Meg', :pets => [sparky])
132
151
 
133
152
  meg.pets.find(sparky._id).should == sparky # oid
134
153
  meg.pets.find(sparky.id.to_s).should == sparky # string
135
154
  end
136
155
 
156
+ context "count" do
157
+ should "default to 0" do
158
+ @owner_class.new.pets.count.should == 0
159
+ end
160
+
161
+ should "return correct count if any are embedded" do
162
+ owner = @owner_class.new(:name => 'Meg')
163
+ owner.pets = [@pet_class.new, @pet_class.new]
164
+ owner.pets.count.should == 2
165
+ owner.save
166
+ owner.reload
167
+ owner.pets.count.should == 2
168
+ end
169
+ end
170
+
137
171
  context "extending the association" do
138
172
  setup do
139
173
  @address_class = EDoc do
@@ -112,7 +112,7 @@ class DirtyTest < Test::Unit::TestCase
112
112
  should "be hash of keys with values of changes if there are changes" do
113
113
  doc = @document.new
114
114
  doc.phrase = 'A penny saved is a penny earned.'
115
- doc.changes.should == {'phrase' => [nil, 'A penny saved is a penny earned.']}
115
+ doc.changes['phrase'].should == [nil, 'A penny saved is a penny earned.']
116
116
  end
117
117
  end
118
118