mongoid 0.8.7 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.7
1
+ 0.8.8
@@ -44,6 +44,17 @@ module Mongoid #:nodoc:
44
44
  object
45
45
  end
46
46
 
47
+ # Creates a new Document and adds it to the association collection. The
48
+ # document created will be of the same class as the others in the
49
+ # association, and the attributes will be passed into the constructor and
50
+ # the new object will then be saved.
51
+ #
52
+ # Returns the newly created object.
53
+ def create(attributes)
54
+ object = build(attributes)
55
+ object.save
56
+ end
57
+
47
58
  # Finds a document in this association.
48
59
  # If :all is passed, returns all the documents
49
60
  # If an id is passed, will return the document for that id.
@@ -60,9 +71,7 @@ module Mongoid #:nodoc:
60
71
  # This then delegated all methods to the array class since this is
61
72
  # essentially a proxy to an array itself.
62
73
  def initialize(document, options)
63
- @parent = document
64
- @association_name = options.name
65
- @klass = options.klass
74
+ @parent, @association_name, @klass = document, options.name, options.klass
66
75
  attributes = document.attributes[@association_name]
67
76
  @documents = attributes ? attributes.collect do |attribute|
68
77
  child = @klass.instantiate(attribute)
@@ -5,7 +5,23 @@ module Mongoid #:nodoc:
5
5
 
6
6
  delegate :valid?, :to => :document
7
7
 
8
- attr_accessor :klass
8
+ attr_accessor :klass, :parent, :association_name
9
+
10
+ # Build a new object for the association.
11
+ def build(attributes)
12
+ @document = @klass.instantiate(attributes)
13
+ @document.parentize(@parent, @association_name)
14
+ @document.notify
15
+ decorate!
16
+ self
17
+ end
18
+
19
+ # Create a new object for the association and save it.
20
+ def create(attributes)
21
+ build(attributes)
22
+ @document.save
23
+ self
24
+ end
9
25
 
10
26
  # Creates the new association by finding the attributes in
11
27
  # the parent document with its name, and instantiating a
@@ -14,7 +30,7 @@ module Mongoid #:nodoc:
14
30
  # All method calls on this object will then be delegated
15
31
  # to the internal document itself.
16
32
  def initialize(document, options)
17
- @klass = options.klass
33
+ @klass, @parent, @association_name = options.klass, document, options.name
18
34
  attributes = document.attributes[options.name]
19
35
  @document = klass.instantiate(attributes || {})
20
36
  @document.parentize(document, options.name)
@@ -113,7 +113,8 @@ module Mongoid #:nodoc:
113
113
 
114
114
  end
115
115
 
116
- # Performs equality checking on the attributes.
116
+ # Performs equality checking on the attributes. For now we chack against
117
+ # all attributes excluding timestamps on the object.
117
118
  def ==(other)
118
119
  return false unless other.is_a?(Document)
119
120
  @attributes.except(:modified_at).except(:created_at) ==
@@ -146,8 +147,8 @@ module Mongoid #:nodoc:
146
147
  self.class.fields
147
148
  end
148
149
 
149
- # Get the id associated with this object.
150
- # This is in essence the primary key.
150
+ # Get the id associated with this object. This will pull the _id value out
151
+ # of the attributes +Hash+.
151
152
  def id
152
153
  @attributes[:_id]
153
154
  end
@@ -160,8 +161,20 @@ module Mongoid #:nodoc:
160
161
  alias :_id :id
161
162
  alias :_id= :id=
162
163
 
163
- # Instantiate a new Document, setting the Document's attributes if given.
164
- # If no attributes are provided, they will be initialized with an empty Hash.
164
+ # Instantiate a new +Document+, setting the Document's attributes if
165
+ # given. If no attributes are provided, they will be initialized with
166
+ # an empty +Hash+.
167
+ #
168
+ # If a primary key is defined, the document's id will be set to that key,
169
+ # otherwise it will be set to a fresh +Mongo::ObjectID+ string.
170
+ #
171
+ # Options:
172
+ #
173
+ # attrs: The attributes +Hash+ to set up the document with.
174
+ #
175
+ # Example:
176
+ #
177
+ # <tt>Person.new(:title => "Mr", :age => 30)</tt>
165
178
  def initialize(attrs = {})
166
179
  @attributes = {}.with_indifferent_access
167
180
  process(defaults.merge(attrs))
@@ -169,34 +182,72 @@ module Mongoid #:nodoc:
169
182
  generate_key
170
183
  end
171
184
 
185
+ # Returns the class name plus its attributes.
172
186
  def inspect
173
187
  "#{self.class.name} : #{@attributes.inspect}"
174
188
  end
175
189
 
176
- # Return the +Document+ primary key.
190
+ # Return the +Document+ primary key. This will only exist if a key has been
191
+ # set up on the +Document+ and will return an array of fields.
192
+ #
193
+ # Example:
194
+ #
195
+ # class Person < Mongoid::Document
196
+ # field :first_name
197
+ # field :last_name
198
+ # key :first_name, :last_name
199
+ # end
200
+ #
201
+ # <tt>person.primary_key #[:first_name, :last_name]</tt>
177
202
  def primary_key
178
203
  self.class.primary_key
179
204
  end
180
205
 
181
- # Returns true is the Document has not been persisted to the database, false if it has.
206
+ # Returns true is the +Document+ has not been persisted to the database,
207
+ # false if it has. This is determined by the instance variable @new_record
208
+ # and NOT if the object has an id.
182
209
  def new_record?
183
210
  @new_record == true
184
211
  end
185
212
 
186
- # Notify observers that this Document has changed.
213
+ # Set the changed state of the +Document+ then notify observers that it has changed.
214
+ #
215
+ # Example:
216
+ #
217
+ # <tt>person.notify</tt>
187
218
  def notify
188
219
  changed(true)
189
220
  notify_observers(self)
190
221
  end
191
222
 
192
- # Sets the parent object
223
+ # Sets up a child/parent association. This is used for newly created
224
+ # objects so they can be properly added to the graph and have the parent
225
+ # observers set up properly.
226
+ #
227
+ # Options:
228
+ #
229
+ # abject: The parent object that needs to be set for the child.
230
+ # association_name: The name of the association for the child.
231
+ #
232
+ # Example:
233
+ #
234
+ # <tt>address.parentize(person, :addresses)</tt>
193
235
  def parentize(object, association_name)
194
236
  self.parent = object
195
237
  self.association_name = association_name
196
238
  add_observer(object)
197
239
  end
198
240
 
199
- # Read from the attributes hash.
241
+ # Read a value from the +Document+ attributes. If the value does not exist
242
+ # it will return nil.
243
+ #
244
+ # Options:
245
+ #
246
+ # name: The name of the attribute to get.
247
+ #
248
+ # Example:
249
+ #
250
+ # <tt>person.read_attribute(:title)</tt>
200
251
  def read_attribute(name)
201
252
  fields[name].get(@attributes[name])
202
253
  end
@@ -206,26 +257,55 @@ module Mongoid #:nodoc:
206
257
  @attributes = collection.find_one(:_id => id).with_indifferent_access
207
258
  end
208
259
 
209
- # Return the root +Document+ in the object graph.
260
+ # Return the root +Document+ in the object graph. If the current +Document+
261
+ # is the root object in the graph it will return self.
210
262
  def root
211
263
  object = self
212
264
  while (object.parent) do object = object.parent; end
213
265
  object || self
214
266
  end
215
267
 
216
- # Returns the id of the Document
268
+ # Returns the id of the Document, used in Rails compatibility.
217
269
  def to_param
218
- id.to_s
270
+ id
219
271
  end
220
272
 
221
- # Update the document based on notify from child
273
+ # Observe a notify call from a child +Document+. This will either update
274
+ # existing attributes on the +Document+ or clear them out for the child if
275
+ # the clear boolean is provided.
276
+ #
277
+ # Options:
278
+ #
279
+ # child: The child +Document+ that sent the notification.
280
+ # clear: Will clear out the child's attributes if set to true.
281
+ #
282
+ # Example:
283
+ #
284
+ # <tt>person.notify_observers(self)</tt> will cause this method to execute.
285
+ #
286
+ # This will also cause the observing +Document+ to notify it's parent if
287
+ # there is any.
222
288
  def update(child, clear = false)
223
289
  @attributes.insert(child.association_name, child.attributes) unless clear
224
290
  @attributes.delete(child.association_name) if clear
225
291
  notify
226
292
  end
227
293
 
228
- # Write to the attributes hash.
294
+ # Write a single attribute to the +Document+ attribute +Hash+. This will
295
+ # also fire the before and after update callbacks, and perform any
296
+ # necessary typecasting.
297
+ #
298
+ # Options:
299
+ #
300
+ # name: The name of the attribute to update.
301
+ # value: The value to set for the attribute.
302
+ #
303
+ # Example:
304
+ #
305
+ # <tt>person.write_attribute(:title, "Mr.")</tt>
306
+ #
307
+ # This will also cause the observing +Document+ to notify it's parent if
308
+ # there is any.
229
309
  def write_attribute(name, value)
230
310
  run_callbacks(:before_update)
231
311
  @attributes[name] = fields[name].set(value)
@@ -233,14 +313,26 @@ module Mongoid #:nodoc:
233
313
  notify
234
314
  end
235
315
 
236
- # Writes all the attributes of this Document, and delegate up to
237
- # the parent.
316
+ # Writes the supplied attributes +Hash+ to the +Document+. This will only
317
+ # overwrite existing attributes if they are present in the new +Hash+, all
318
+ # others will be preserved.
319
+ #
320
+ # Options:
321
+ #
322
+ # attrs: The +Hash+ of new attributes to set on the +Document+
323
+ #
324
+ # Example:
325
+ #
326
+ # <tt>person.write_attributes(:title => "Mr.")</tt>
327
+ #
328
+ # This will also cause the observing +Document+ to notify it's parent if
329
+ # there is any.
238
330
  def write_attributes(attrs)
239
331
  process(attrs)
240
332
  notify
241
333
  end
242
334
 
243
- private
335
+ protected
244
336
  def generate_key
245
337
  if primary_key
246
338
  values = primary_key.collect { |key| @attributes[key] }
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongoid}
8
- s.version = "0.8.7"
8
+ s.version = "0.8.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Durran Jordan"]
@@ -35,6 +35,33 @@ describe Mongoid::Document do
35
35
  person.attributes[:title].should == "Test"
36
36
  end
37
37
 
38
+ context "when creating a has many" do
39
+
40
+ before do
41
+ @person = Person.new(:title => "Esquire")
42
+ @person.addresses.create(:street => "Nan Jing Dong Lu", :city => "Shanghai")
43
+ end
44
+
45
+ it "should create and save the entire graph" do
46
+ person = Person.find(@person.id)
47
+ person.addresses.first.street.should == "Nan Jing Dong Lu"
48
+ end
49
+
50
+ end
51
+
52
+ context "when creating a has one" do
53
+
54
+ before do
55
+ @person = Person.new(:title => "Esquire")
56
+ @person.name.create(:first_name => "Jorge")
57
+ end
58
+
59
+ it "should create and save the entire graph" do
60
+ person = Person.find(@person.id)
61
+ person.name.first_name.should == "Jorge"
62
+ end
63
+
64
+ end
38
65
  end
39
66
 
40
67
  describe "#find" do
@@ -9,25 +9,6 @@ describe Mongoid::Associations::HasMany do
9
9
  @document = stub(:attributes => @attributes, :add_observer => true, :update => true)
10
10
  end
11
11
 
12
- describe "#update" do
13
-
14
- before do
15
- @address = Address.new(:street => "Madison Ave")
16
- @person = Person.new(:title => "Sir")
17
- Mongoid::Associations::HasMany.update([@address], @person, Mongoid::Associations::Options.new(:name => :addresses))
18
- end
19
-
20
- it "parentizes the child document" do
21
- @address.parent.should == @person
22
- end
23
-
24
- it "sets the attributes of the child on the parent" do
25
- @person.attributes[:addresses].should ==
26
- [{ "_id" => "madison-ave", "street" => "Madison Ave" }]
27
- end
28
-
29
- end
30
-
31
12
  describe "#[]" do
32
13
 
33
14
  before do
@@ -56,7 +37,10 @@ describe Mongoid::Associations::HasMany do
56
37
  describe "#<<" do
57
38
 
58
39
  before do
59
- @association = Mongoid::Associations::HasMany.new(@document, Mongoid::Associations::Options.new(:name => :addresses))
40
+ @association = Mongoid::Associations::HasMany.new(
41
+ @document,
42
+ Mongoid::Associations::Options.new(:name => :addresses)
43
+ )
60
44
  @address = Address.new
61
45
  end
62
46
 
@@ -74,22 +58,50 @@ describe Mongoid::Associations::HasMany do
74
58
 
75
59
  end
76
60
 
77
- describe "#concat" do
61
+ describe "#build" do
78
62
 
79
63
  before do
80
- @association = Mongoid::Associations::HasMany.new(@document, Mongoid::Associations::Options.new(:name => :addresses))
81
- @address = Address.new
64
+ @association = Mongoid::Associations::HasMany.new(
65
+ @document,
66
+ Mongoid::Associations::Options.new(:name => :addresses)
67
+ )
82
68
  end
83
69
 
84
- it "adds the parent document before appending to the array" do
85
- @association.concat [@address]
70
+ it "adds a new document to the array with the suppied parameters" do
71
+ @association.build({ :street => "Street 1" })
86
72
  @association.length.should == 3
87
- @address.parent.should == @document
73
+ @association[2].should be_a_kind_of(Address)
74
+ @association[2].street.should == "Street 1"
75
+ end
76
+
77
+ it "returns the newly built object in the association" do
78
+ address = @association.build({ :street => "Yet Another" })
79
+ address.should be_a_kind_of(Address)
80
+ address.street.should == "Yet Another"
88
81
  end
89
82
 
90
83
  end
91
84
 
92
- describe "#push" do
85
+ describe "#create" do
86
+
87
+ before do
88
+ @association = Mongoid::Associations::HasMany.new(
89
+ @document,
90
+ Mongoid::Associations::Options.new(:name => :addresses)
91
+ )
92
+ @address = Address.new(:street => "Yet Another")
93
+ end
94
+
95
+ it "builds and saves a new object" do
96
+ Mongoid::Commands::Create.expects(:execute).returns(@address)
97
+ address = @association.create({ :street => "Yet Another" })
98
+ address.should be_a_kind_of(Address)
99
+ address.street.should == "Yet Another"
100
+ end
101
+
102
+ end
103
+
104
+ describe "#concat" do
93
105
 
94
106
  before do
95
107
  @association = Mongoid::Associations::HasMany.new(@document, Mongoid::Associations::Options.new(:name => :addresses))
@@ -97,30 +109,24 @@ describe Mongoid::Associations::HasMany do
97
109
  end
98
110
 
99
111
  it "adds the parent document before appending to the array" do
100
- @association.push @address
112
+ @association.concat [@address]
101
113
  @association.length.should == 3
102
114
  @address.parent.should == @document
103
115
  end
104
116
 
105
117
  end
106
118
 
107
- describe "#build" do
119
+ describe "#push" do
108
120
 
109
121
  before do
110
122
  @association = Mongoid::Associations::HasMany.new(@document, Mongoid::Associations::Options.new(:name => :addresses))
123
+ @address = Address.new
111
124
  end
112
125
 
113
- it "adds a new document to the array with the suppied parameters" do
114
- @association.build({ :street => "Street 1" })
126
+ it "adds the parent document before appending to the array" do
127
+ @association.push @address
115
128
  @association.length.should == 3
116
- @association[2].should be_a_kind_of(Address)
117
- @association[2].street.should == "Street 1"
118
- end
119
-
120
- it "returns the newly built object in the association" do
121
- address = @association.build({ :street => "Yet Another" })
122
- address.should be_a_kind_of(Address)
123
- address.street.should == "Yet Another"
129
+ @address.parent.should == @document
124
130
  end
125
131
 
126
132
  end
@@ -217,4 +223,23 @@ describe Mongoid::Associations::HasMany do
217
223
 
218
224
  end
219
225
 
226
+ describe "#update" do
227
+
228
+ before do
229
+ @address = Address.new(:street => "Madison Ave")
230
+ @person = Person.new(:title => "Sir")
231
+ Mongoid::Associations::HasMany.update([@address], @person, Mongoid::Associations::Options.new(:name => :addresses))
232
+ end
233
+
234
+ it "parentizes the child document" do
235
+ @address.parent.should == @person
236
+ end
237
+
238
+ it "sets the attributes of the child on the parent" do
239
+ @person.attributes[:addresses].should ==
240
+ [{ "_id" => "madison-ave", "street" => "Madison Ave" }]
241
+ end
242
+
243
+ end
244
+
220
245
  end
@@ -7,25 +7,44 @@ describe Mongoid::Associations::HasOne do
7
7
  @document = stub(:attributes => @attributes, :update => true)
8
8
  end
9
9
 
10
- describe "#update" do
10
+ describe "#build" do
11
11
 
12
- before do
13
- @name = Name.new(:first_name => "Donald")
14
- @person = Person.new(:title => "Sir")
15
- Mongoid::Associations::HasOne.update(
16
- @name,
17
- @person,
18
- Mongoid::Associations::Options.new(:name => :name)
19
- )
20
- end
12
+ context "when attributes provided" do
13
+
14
+ before do
15
+ @association = Mongoid::Associations::HasOne.new(
16
+ @document,
17
+ Mongoid::Associations::Options.new(:name => :mixed_drink)
18
+ )
19
+ end
20
+
21
+ it "replaces the existing has_one" do
22
+ drink = @association.build({ :name => "Sapphire and Tonic" })
23
+ drink.name.should == "Sapphire and Tonic"
24
+ end
21
25
 
22
- it "parentizes the child document" do
23
- @name.parent.should == @person
24
26
  end
25
27
 
26
- it "sets the attributes of the child on the parent" do
27
- @person.attributes[:name].should ==
28
- { "_id" => "donald", "first_name" => "Donald" }
28
+ end
29
+
30
+ describe "#create" do
31
+
32
+ context "when attributes provided" do
33
+
34
+ before do
35
+ @association = Mongoid::Associations::HasOne.new(
36
+ @document,
37
+ Mongoid::Associations::Options.new(:name => :mixed_drink)
38
+ )
39
+ @drink = MixedDrink.new(:name => "Sapphire and Tonic")
40
+ end
41
+
42
+ it "replaces and saves the existing has_one" do
43
+ Mongoid::Commands::Create.expects(:execute).returns(@drink)
44
+ drink = @association.create({ :name => "Sapphire and Tonic" })
45
+ drink.name.should == "Sapphire and Tonic"
46
+ end
47
+
29
48
  end
30
49
 
31
50
  end
@@ -58,4 +77,27 @@ describe Mongoid::Associations::HasOne do
58
77
 
59
78
  end
60
79
 
80
+ describe "#update" do
81
+
82
+ before do
83
+ @name = Name.new(:first_name => "Donald")
84
+ @person = Person.new(:title => "Sir")
85
+ Mongoid::Associations::HasOne.update(
86
+ @name,
87
+ @person,
88
+ Mongoid::Associations::Options.new(:name => :name)
89
+ )
90
+ end
91
+
92
+ it "parentizes the child document" do
93
+ @name.parent.should == @person
94
+ end
95
+
96
+ it "sets the attributes of the child on the parent" do
97
+ @person.attributes[:name].should ==
98
+ { "_id" => "donald", "first_name" => "Donald" }
99
+ end
100
+
101
+ end
102
+
61
103
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.7
4
+ version: 0.8.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Durran Jordan