mongo_doc_rails2 0.6.1

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 (142) hide show
  1. data/.document +5 -0
  2. data/.gitignore +8 -0
  3. data/HISTORY.md +11 -0
  4. data/LICENSE +20 -0
  5. data/README.textile +185 -0
  6. data/Rakefile +188 -0
  7. data/TODO +40 -0
  8. data/VERSION +1 -0
  9. data/data/.gitignore +2 -0
  10. data/examples/simple_document.rb +46 -0
  11. data/examples/simple_object.rb +34 -0
  12. data/features/collections.feature +9 -0
  13. data/features/embed_hash.feature +16 -0
  14. data/features/finders.feature +76 -0
  15. data/features/indexes.feature +28 -0
  16. data/features/mongodb.yml +7 -0
  17. data/features/mongodoc_base.feature +128 -0
  18. data/features/new_record.feature +36 -0
  19. data/features/partial_updates.feature +95 -0
  20. data/features/removing_documents.feature +68 -0
  21. data/features/saving_an_object.feature +15 -0
  22. data/features/scopes.feature +66 -0
  23. data/features/step_definitions/collection_steps.rb +17 -0
  24. data/features/step_definitions/document_steps.rb +149 -0
  25. data/features/step_definitions/documents.rb +40 -0
  26. data/features/step_definitions/embed_hash_steps.rb +6 -0
  27. data/features/step_definitions/finder_steps.rb +15 -0
  28. data/features/step_definitions/index_steps.rb +10 -0
  29. data/features/step_definitions/json_steps.rb +9 -0
  30. data/features/step_definitions/object_steps.rb +50 -0
  31. data/features/step_definitions/objects.rb +24 -0
  32. data/features/step_definitions/partial_update_steps.rb +31 -0
  33. data/features/step_definitions/query_steps.rb +66 -0
  34. data/features/step_definitions/removing_documents_steps.rb +14 -0
  35. data/features/step_definitions/scope_steps.rb +18 -0
  36. data/features/step_definitions/string_casting_steps.rb +29 -0
  37. data/features/step_definitions/util_steps.rb +7 -0
  38. data/features/string_casting.feature +10 -0
  39. data/features/support/support.rb +10 -0
  40. data/features/using_criteria.feature +142 -0
  41. data/lib/mongo_doc.rb +12 -0
  42. data/lib/mongo_doc/associations.rb +109 -0
  43. data/lib/mongo_doc/associations/collection_proxy.rb +121 -0
  44. data/lib/mongo_doc/associations/document_proxy.rb +65 -0
  45. data/lib/mongo_doc/associations/hash_proxy.rb +102 -0
  46. data/lib/mongo_doc/associations/proxy_base.rb +48 -0
  47. data/lib/mongo_doc/attributes.rb +84 -0
  48. data/lib/mongo_doc/bson.rb +31 -0
  49. data/lib/mongo_doc/collection.rb +82 -0
  50. data/lib/mongo_doc/connection.rb +88 -0
  51. data/lib/mongo_doc/contexts.rb +31 -0
  52. data/lib/mongo_doc/contexts/ids.rb +41 -0
  53. data/lib/mongo_doc/contexts/mongo.rb +272 -0
  54. data/lib/mongo_doc/criteria.rb +70 -0
  55. data/lib/mongo_doc/cursor.rb +32 -0
  56. data/lib/mongo_doc/document.rb +205 -0
  57. data/lib/mongo_doc/ext.rb +16 -0
  58. data/lib/mongo_doc/ext/array.rb +5 -0
  59. data/lib/mongo_doc/ext/binary.rb +7 -0
  60. data/lib/mongo_doc/ext/boolean_class.rb +17 -0
  61. data/lib/mongo_doc/ext/date.rb +19 -0
  62. data/lib/mongo_doc/ext/date_time.rb +17 -0
  63. data/lib/mongo_doc/ext/dbref.rb +7 -0
  64. data/lib/mongo_doc/ext/hash.rb +7 -0
  65. data/lib/mongo_doc/ext/min_max_keys.rb +13 -0
  66. data/lib/mongo_doc/ext/nil_class.rb +5 -0
  67. data/lib/mongo_doc/ext/numeric.rb +17 -0
  68. data/lib/mongo_doc/ext/object.rb +19 -0
  69. data/lib/mongo_doc/ext/object_id.rb +7 -0
  70. data/lib/mongo_doc/ext/regexp.rb +5 -0
  71. data/lib/mongo_doc/ext/string.rb +5 -0
  72. data/lib/mongo_doc/ext/symbol.rb +5 -0
  73. data/lib/mongo_doc/ext/time.rb +9 -0
  74. data/lib/mongo_doc/finders.rb +38 -0
  75. data/lib/mongo_doc/index.rb +46 -0
  76. data/lib/mongo_doc/matchers.rb +35 -0
  77. data/lib/mongo_doc/root.rb +26 -0
  78. data/lib/mongo_doc/scope.rb +64 -0
  79. data/lib/mongo_doc/validations.rb +12 -0
  80. data/lib/mongo_doc/validations/macros.rb +11 -0
  81. data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
  82. data/lib/mongoid/contexts/enumerable.rb +151 -0
  83. data/lib/mongoid/contexts/paging.rb +42 -0
  84. data/lib/mongoid/criteria.rb +239 -0
  85. data/lib/mongoid/criterion/complex.rb +21 -0
  86. data/lib/mongoid/criterion/exclusion.rb +65 -0
  87. data/lib/mongoid/criterion/inclusion.rb +93 -0
  88. data/lib/mongoid/criterion/optional.rb +136 -0
  89. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  90. data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
  91. data/lib/mongoid/matchers/all.rb +11 -0
  92. data/lib/mongoid/matchers/default.rb +26 -0
  93. data/lib/mongoid/matchers/exists.rb +13 -0
  94. data/lib/mongoid/matchers/gt.rb +11 -0
  95. data/lib/mongoid/matchers/gte.rb +11 -0
  96. data/lib/mongoid/matchers/in.rb +11 -0
  97. data/lib/mongoid/matchers/lt.rb +11 -0
  98. data/lib/mongoid/matchers/lte.rb +11 -0
  99. data/lib/mongoid/matchers/ne.rb +11 -0
  100. data/lib/mongoid/matchers/nin.rb +11 -0
  101. data/lib/mongoid/matchers/size.rb +11 -0
  102. data/mongo_doc_rails2.gemspec +237 -0
  103. data/mongod.example.yml +2 -0
  104. data/mongodb.example.yml +14 -0
  105. data/perf/mongo_doc_object.rb +83 -0
  106. data/perf/mongo_document.rb +84 -0
  107. data/perf/ruby_driver.rb +49 -0
  108. data/script/console +8 -0
  109. data/spec/array_including_argument_matcher.rb +62 -0
  110. data/spec/associations/collection_proxy_spec.rb +233 -0
  111. data/spec/associations/document_proxy_spec.rb +45 -0
  112. data/spec/associations/hash_proxy_spec.rb +181 -0
  113. data/spec/associations/proxy_base_spec.rb +92 -0
  114. data/spec/associations_spec.rb +218 -0
  115. data/spec/attributes_accessor_spec.rb +33 -0
  116. data/spec/attributes_spec.rb +145 -0
  117. data/spec/bson_matchers.rb +54 -0
  118. data/spec/bson_spec.rb +196 -0
  119. data/spec/collection_spec.rb +169 -0
  120. data/spec/connection_spec.rb +147 -0
  121. data/spec/contexts/ids_spec.rb +49 -0
  122. data/spec/contexts/mongo_spec.rb +235 -0
  123. data/spec/contexts_spec.rb +56 -0
  124. data/spec/criteria_spec.rb +69 -0
  125. data/spec/cursor_spec.rb +91 -0
  126. data/spec/document_ext.rb +9 -0
  127. data/spec/document_spec.rb +553 -0
  128. data/spec/embedded_save_spec.rb +73 -0
  129. data/spec/ext_spec.rb +89 -0
  130. data/spec/finders_spec.rb +61 -0
  131. data/spec/hash_matchers.rb +27 -0
  132. data/spec/index_spec.rb +79 -0
  133. data/spec/matchers_spec.rb +342 -0
  134. data/spec/mongodb.yml +6 -0
  135. data/spec/mongodb_pairs.yml +8 -0
  136. data/spec/new_record_spec.rb +128 -0
  137. data/spec/root_spec.rb +41 -0
  138. data/spec/scope_spec.rb +79 -0
  139. data/spec/spec.opts +2 -0
  140. data/spec/spec_helper.rb +14 -0
  141. data/spec/validations_spec.rb +30 -0
  142. metadata +346 -0
@@ -0,0 +1,2 @@
1
+ mongod: /usr/local/bin/mongod
2
+ dbpath: /data/db
@@ -0,0 +1,14 @@
1
+ development:
2
+ name: development
3
+ host: localhost
4
+ port: 27017
5
+ options:
6
+ auto_reconnect: true
7
+
8
+ test:
9
+ name: test
10
+ host: localhost
11
+ port: 27017
12
+ options:
13
+ auto_reconnect: true
14
+
@@ -0,0 +1,83 @@
1
+ require "rubygems"
2
+ require "ruby-prof"
3
+ require "mongo_doc"
4
+
5
+ class Person
6
+ attr_accessor :address, :birth_date, :name, :phones
7
+ end
8
+
9
+ class Name
10
+ attr_accessor :family, :given, :middle
11
+ end
12
+
13
+ class Address
14
+ attr_accessor :city, :post_code, :state, :street, :type
15
+ end
16
+
17
+ class Phone
18
+ attr_accessor :country_code, :number, :type
19
+ end
20
+
21
+ class MongoDocObject
22
+ attr_accessor :collection
23
+ attr_accessor :objects
24
+ attr_accessor :ids
25
+
26
+ def initialize
27
+ MongoDoc::Connection.name = 'mongo_doc_object_test'
28
+ self.collection = MongoDoc::Collection.new 'people'
29
+ collection.drop
30
+ end
31
+
32
+ def generate(count)
33
+ self.objects = []
34
+ self.ids = []
35
+ count.times do |i|
36
+ person = Person.new
37
+ person.birth_date = Date.new(1970, 1, 1)
38
+ person.phones = []
39
+
40
+ name = Name.new
41
+ name.given = "James #{i}"
42
+ name.family = "Kirk"
43
+ name.middle = "Tiberius"
44
+
45
+ address = Address.new
46
+ address.street = "1 Starfleet Command Way"
47
+ address.city = "San Francisco"
48
+ address.state = "CA"
49
+ address.post_code = "94133"
50
+ address.type = "Work"
51
+
52
+ phone = Phone.new
53
+ phone.country_code = 1
54
+ phone.number = "415-555-1212"
55
+ phone.type = "Mobile"
56
+
57
+ person.name = name
58
+ person.address = address
59
+ person.phones << phone
60
+
61
+ objects << person
62
+ end
63
+ end
64
+
65
+ def writes(count)
66
+ count.times do |i|
67
+ ids[i] = collection.save(objects[i])
68
+ end
69
+ end
70
+
71
+ def reads(count)
72
+ count.times do |i|
73
+ obj = collection.find_one(ids[i])
74
+ raise 'Not found' unless obj.name.given == objects[i].name.given
75
+ end
76
+ end
77
+
78
+ def query_all
79
+ collection.find.each do |obj|
80
+ given_name = obj.name.given
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,84 @@
1
+ require "benchmark"
2
+ require "ruby-prof"
3
+ require "mongo_doc"
4
+
5
+ class Person
6
+ include MongoDoc::Document
7
+
8
+ attr_accessor :birth_date, :type => Date
9
+
10
+ embed :name
11
+ embed :address
12
+ embed_many :phones
13
+ end
14
+
15
+ class Name
16
+ include MongoDoc::Document
17
+
18
+ attr_accessor :given
19
+ attr_accessor :family
20
+ attr_accessor :middle
21
+ end
22
+
23
+ class Address
24
+ include MongoDoc::Document
25
+
26
+ attr_accessor :street
27
+ attr_accessor :city
28
+ attr_accessor :state
29
+ attr_accessor :post_code
30
+ attr_accessor :type
31
+ end
32
+
33
+ class Phone
34
+ include MongoDoc::Document
35
+
36
+ attr_accessor :country_code
37
+ attr_accessor :number
38
+ attr_accessor :type
39
+ end
40
+
41
+ class MongoDocument
42
+ attr_accessor :collection
43
+ attr_accessor :documents
44
+
45
+ def initialize
46
+ MongoDoc::Connection.name = 'mongo_doc_object_test'
47
+ self.collection = MongoDoc::Collection.new 'people'
48
+ collection.drop
49
+ end
50
+
51
+ def generate(count)
52
+ self.documents = []
53
+ count.times do |i|
54
+ person = Person.new(:birth_date => Date.new(1970, 1, 1))
55
+ name = Name.new(:given => "James #{i}", :family => "Kirk", :middle => "Tiberius")
56
+ address = Address.new(:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work")
57
+ phone = Phone.new(:country_code => 1, :number => "415-555-1212", :type => "Mobile")
58
+ person.name = name
59
+ person.address = address
60
+ person.phones << phone
61
+
62
+ documents << person
63
+ end
64
+ end
65
+
66
+ def writes(count)
67
+ count.times do |i|
68
+ documents[i].save
69
+ end
70
+ end
71
+
72
+ def reads(count)
73
+ count.times do |i|
74
+ doc = collection.find_one(documents[i]._id)
75
+ raise 'Not found' unless doc.name.given == documents[i].name.given
76
+ end
77
+ end
78
+
79
+ def query_all
80
+ collection.find.each do |doc|
81
+ given_name = doc.name.given
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,49 @@
1
+ require "rubygems"
2
+ require "ruby-prof"
3
+ require "mongo_doc"
4
+
5
+ class RubyDriver
6
+ attr_accessor :collection
7
+ attr_accessor :objects
8
+ attr_accessor :ids
9
+
10
+ def initialize
11
+ MongoDoc::Connection.name = 'ruby_driver_test'
12
+ self.collection = MongoDoc::Connection.database.collection 'people'
13
+ collection.drop
14
+ end
15
+
16
+ def generate(count)
17
+ self.objects = []
18
+ self.ids = []
19
+ count.times do |i|
20
+ person = {:birth_date => Date.new(1970, 1, 1).to_bson, :phones => []}
21
+ name = {:given => "James #{i}", :family => "Kirk", :middle => "Tiberius"}
22
+ address = {:street => "1 Starfleet Command Way", :city => "San Francisco", :state => "CA", :post_code => "94133", :type => "Work"}
23
+ phone = {:country_code => 1, :number => "415-555-1212", :type => "Mobile"}
24
+ person[:name] = name
25
+ person[:address] = address
26
+ person[:phones] << phone
27
+ objects << person
28
+ end
29
+ end
30
+
31
+ def writes(count)
32
+ count.times do |i|
33
+ ids[i] = collection.save(objects[i])
34
+ end
35
+ end
36
+
37
+ def reads(count)
38
+ count.times do |i|
39
+ obj = collection.find_one(ids[i])
40
+ raise 'Not found' unless obj and obj['name']['given'] == objects[i][:name][:given]
41
+ end
42
+ end
43
+
44
+ def query_all
45
+ collection.find().each do |obj|
46
+ given_name = obj['name']['given']
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+
5
+ require 'irb'
6
+ require 'mongo_doc'
7
+
8
+ IRB.start(__FILE__)
@@ -0,0 +1,62 @@
1
+ # From http://gist.github.com/62943
2
+ # Author http://github.com/trotter
3
+ module Spec
4
+ module Mocks
5
+ module ArgumentMatchers
6
+
7
+ class ArrayIncludingMatcher
8
+ # We'll allow an array of arguments to be passed in, so that you can do
9
+ # things like obj.should_receive(:blah).with(array_including('a', 'b'))
10
+ def initialize(*expected)
11
+ @expected = expected
12
+ end
13
+
14
+ # actual is the array (hopefully) passed to the method by the user.
15
+ # We'll check that it includes all the expected values, and return false
16
+ # if it doesn't or if we blow up because #include? is not defined.
17
+ def ==(actual)
18
+ @expected.each do |expected|
19
+ return false unless actual.include?(expected)
20
+ end
21
+ true
22
+ rescue NoMethodError => ex
23
+ return false
24
+ end
25
+
26
+ def description
27
+ "array_including(#{@expected.join(', ')})"
28
+ end
29
+ end
30
+
31
+ class ArrayNotIncludingMatcher
32
+ def initialize(*expected)
33
+ @expected = expected
34
+ end
35
+
36
+ def ==(actual)
37
+ @expected.each do |expected|
38
+ return false if actual.include?(expected)
39
+ end
40
+ true
41
+ rescue NoMethodError => ex
42
+ return false
43
+ end
44
+
45
+ def description
46
+ "array_not_including(#{@expected.join(', ')})"
47
+ end
48
+ end
49
+
50
+ # array_including is a helpful wrapper that allows us to actually type
51
+ # #with(array_including(...)) instead of ArrayIncludingMatcher.new(...)
52
+ def array_including(*args)
53
+ ArrayIncludingMatcher.new(*args)
54
+ end
55
+
56
+ def array_not_including(*args)
57
+ ArrayNotIncludingMatcher.new(*args)
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,233 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '/spec_helper'))
2
+
3
+ describe MongoDoc::Associations::CollectionProxy do
4
+ class CollectionProxyTest
5
+ include MongoDoc::Document
6
+
7
+ attr_accessor :name
8
+ end
9
+
10
+ let(:name) { 'embed_many_name' }
11
+ let(:root) { CollectionProxyTest.new }
12
+ let(:proxy) { MongoDoc::Associations::CollectionProxy.new(:assoc_name => name, :assoc_class => CollectionProxyTest, :root => root, :parent => root) }
13
+ let(:item) { CollectionProxyTest.new }
14
+
15
+ describe "#_modifier_path" do
16
+ it "cascades to child documents with our assoc name and $" do
17
+ document = stub
18
+ proxy.stub(:collection => [document])
19
+ document.should_receive(:_modifier_path=).with("new.path.#{name}.$")
20
+ MongoDoc::Associations::ProxyBase.stub(:is_document?).and_return(true)
21
+ proxy._modifier_path = 'new.path'
22
+ end
23
+ end
24
+
25
+ describe "#_selector_path=" do
26
+ it "cascades to child documents" do
27
+ document = stub
28
+ proxy.stub(:collection => [document])
29
+ document.should_receive("_selector_path=").with("new.path.#{name}")
30
+ MongoDoc::Associations::ProxyBase.stub(:is_document?).and_return(true)
31
+ proxy._selector_path = 'new.path'
32
+ end
33
+ end
34
+
35
+ context "#attach_document" do
36
+ it "sets the Document's modifier path to our modifier path" do
37
+ item.should_receive(:_modifier_path=).with('embed_many_name.$')
38
+ proxy.send(:attach_document, item)
39
+ end
40
+
41
+ it "sets the Document's selector path to our selector path" do
42
+ item.should_receive(:_selector_path=).with('embed_many_name')
43
+ proxy.send(:attach_document, item)
44
+ end
45
+ end
46
+
47
+ context "#<<" do
48
+ it "appends the item to the collection" do
49
+ (proxy << item).should include(item)
50
+ end
51
+
52
+ context "when the item is a Hash" do
53
+ let(:hash) {{:name => 'hash'}}
54
+
55
+ it "does not register a save observer" do
56
+ root.should_not_receive(:register_save_observer)
57
+ proxy << hash
58
+ end
59
+
60
+ it "does not set the root" do
61
+ hash.should_not_receive(:_root=)
62
+ proxy << hash
63
+ end
64
+
65
+ it "adds the hash to the collection" do
66
+ proxy << hash
67
+ proxy.should include(hash)
68
+ end
69
+ end
70
+
71
+ context "when the item is not a MongoDoc::Document" do
72
+ let(:other_item) {'not a doc'}
73
+
74
+ it "does not register a save observer" do
75
+ root.should_not_receive(:register_save_observer)
76
+ proxy << other_item
77
+ end
78
+
79
+ it "does not set the root" do
80
+ other_item.should_not_receive(:_root=)
81
+ proxy << other_item
82
+ end
83
+
84
+ it "adds the item to the collection" do
85
+ proxy << other_item
86
+ proxy.should include(other_item)
87
+ end
88
+ end
89
+
90
+ context "when the item is a MongoDoc::Document" do
91
+ it "registers a save observer" do
92
+ root.should_receive(:register_save_observer)
93
+ proxy << item
94
+ end
95
+
96
+ it "sets the root" do
97
+ proxy << item
98
+ item._root.should == root
99
+ end
100
+ end
101
+
102
+ context "when the item is an array" do
103
+ it "adds the array" do
104
+ array = ['something else']
105
+ proxy << array
106
+ proxy.should include(array)
107
+ end
108
+ end
109
+ end
110
+
111
+ context "#[]=" do
112
+ it "sets the item at the index" do
113
+ proxy[1] = item
114
+ proxy[1].should == item
115
+ end
116
+
117
+ context "when the item is not a MongoDoc::Document" do
118
+ let(:other_item) {'not a doc'}
119
+
120
+ it "does not register a save observer" do
121
+ root.should_not_receive(:register_save_observer)
122
+ proxy[1] = other_item
123
+ end
124
+
125
+ it "does not set the root" do
126
+ other_item.should_not_receive(:_root=)
127
+ proxy[1] = other_item
128
+ end
129
+
130
+ it "adds the item to the collection" do
131
+ proxy[1] = other_item
132
+ proxy.should include(other_item)
133
+ end
134
+ end
135
+
136
+ context "when the item is a MongoDoc::Document" do
137
+ it "registers a save observer" do
138
+ root.should_receive(:register_save_observer)
139
+ proxy[1] = item
140
+ end
141
+
142
+ it "sets the root" do
143
+ proxy[1] = item
144
+ item._root.should == root
145
+ end
146
+ end
147
+ end
148
+
149
+ context "#concat" do
150
+ it "appends the items from the array to self" do
151
+ proxy.concat([item])
152
+ proxy.should include(item)
153
+ end
154
+ end
155
+
156
+ context "#replace" do
157
+ it "clears the existing collection" do
158
+ proxy.should_receive(:clear)
159
+ proxy.replace([item])
160
+ end
161
+
162
+ it "concats the other onto self" do
163
+ other = [item]
164
+ proxy.should_receive(:concat).with(other)
165
+ proxy.replace(other)
166
+ end
167
+ end
168
+
169
+ context "#unshift" do
170
+ let(:proxy_with_item) { proxy << 'other' }
171
+
172
+ it "adds the item to the front of the collection" do
173
+ proxy_with_item.unshift(item)
174
+ proxy_with_item[0].should == item
175
+ end
176
+
177
+ context "when the item is not a MongoDoc::Document" do
178
+ let(:other_item) {'not a doc'}
179
+
180
+ it "does not register a save observer" do
181
+ root.should_not_receive(:register_save_observer)
182
+ proxy_with_item.unshift(other_item)
183
+ end
184
+
185
+ it "does not set the root" do
186
+ other_item.should_not_receive(:_root=)
187
+ proxy_with_item.unshift(other_item)
188
+ end
189
+
190
+ it "adds the item to the front of the collection" do
191
+ proxy_with_item.unshift(other_item)
192
+ proxy_with_item[0].should == other_item
193
+ end
194
+ end
195
+
196
+ context "when the item is a MongoDoc::Document" do
197
+ let(:new_item) { CollectionProxyTest.new }
198
+
199
+ it "registers a save observer" do
200
+ root.should_receive(:register_save_observer)
201
+ proxy_with_item.unshift(new_item)
202
+ end
203
+
204
+ it "sets the root" do
205
+ proxy_with_item.unshift(new_item)
206
+ new_item._root.should == root
207
+ end
208
+
209
+ it "adds the item to the front of the collection" do
210
+ proxy_with_item.unshift(new_item)
211
+ proxy_with_item[0].should == new_item
212
+ end
213
+ end
214
+ end
215
+
216
+ context "#build" do
217
+ let(:name) {'built'}
218
+
219
+ it "adds a built item to the collection" do
220
+ proxy.build({:name => name}).last.name.should == name
221
+ end
222
+
223
+ it "registers a save observer" do
224
+ root.should_receive(:register_save_observer)
225
+ proxy.build({:name => name})
226
+ end
227
+
228
+ it "sets the root" do
229
+ proxy.build({:name => name})
230
+ proxy.last._root.should == root
231
+ end
232
+ end
233
+ end