mongoid 0.8.7 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
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