Skip to content

Commit

Permalink
Refactored _root_document and _parent_document. Documents now know th…
Browse files Browse the repository at this point in the history
…ey are _root_documents and EmbeddedDocuments now set _root_document when setting _parent_document. Now you only have to set _parent_document, the writer for _root_document is gone and unnecessary.
  • Loading branch information
jnunemaker committed Feb 28, 2010
1 parent 1fe5d69 commit f57a3b2
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 51 deletions.
6 changes: 6 additions & 0 deletions lib/mongo_mapper/document.rb
Expand Up @@ -392,6 +392,12 @@ def reload
end
end

# Used by embedded docs to find root easily without if/respond_to? stuff.
# Documents are always root documents.
def _root_document
self
end

private
def create_or_update(options={})
result = new? ? create(options) : update(options)
Expand Down
7 changes: 6 additions & 1 deletion lib/mongo_mapper/embedded_document.rb
Expand Up @@ -20,7 +20,7 @@ def self.included(model)
plugin Plugins::Serialization
plugin Plugins::Validations

attr_accessor :_root_document, :_parent_document
attr_reader :_root_document, :_parent_document
end

super
Expand Down Expand Up @@ -50,6 +50,11 @@ def save!(options={})
end
result
end

def _parent_document=(value)
@_root_document = value._root_document
@_parent_document = value
end
end # InstanceMethods
end # EmbeddedDocument
end # MongoMapper
13 changes: 1 addition & 12 deletions lib/mongo_mapper/plugins/associations/embedded_collection.rb
Expand Up @@ -30,19 +30,8 @@ def <<(*docs)
alias_method :concat, :<<

private
def _root_document
if owner.respond_to?(:_root_document)
owner._root_document
else
owner
end
end

def assign_references(*docs)
docs.each do |doc|
doc._root_document = _root_document
doc._parent_document = owner
end
docs.each { |doc| doc._parent_document = owner }
end
end
end
Expand Down
3 changes: 3 additions & 0 deletions lib/mongo_mapper/plugins/keys.rb
Expand Up @@ -175,6 +175,9 @@ def attributes=(attrs)
writer_method = "#{name}="

if respond_to?(writer_method)
if writer_method == '_root_document='
puts "_root_document= #{value.inspect}"
end
self.send(writer_method, value)
else
self[name.to_s] = value
Expand Down
46 changes: 23 additions & 23 deletions test/functional/test_embedded_document.rb
Expand Up @@ -7,27 +7,27 @@ def setup
key :first_name, String
key :last_name, String
end

@pet_klass = EDoc do
key :name, String
end

@klass.many :pets, :class => @pet_klass

@address_class = EDoc do
key :city, String
key :state, String
end
end
context "Saving a document with an embedded document" do

context "Saving a document with a key that is an embedded document" do
setup do
@klass.key :foo, @address_class

@address = @address_class.new(:city => 'South Bend', :state => 'IN')
@doc = @klass.new(:foo => @address)
end

should "embed embedded document" do
@doc.save
@doc.foo.city.should == 'South Bend'
Expand All @@ -38,16 +38,16 @@ def setup
doc.foo.state.should == 'IN'
end
end

should "correctly instantiate single collection inherited embedded documents" do
document = Doc('Foo') do
key :message, Message
end

doc1 = document.create(:message => Enter.new)
doc1.reload.message.class.should be(Enter)
end

context "new?" do
setup do
@klass.key :foo, @address_class
Expand All @@ -58,65 +58,65 @@ def setup
doc = @klass.new(:foo => address)
address.new?.should == true
end

should "not be new after document is saved" do
address = @address_class.new(:city => 'South Bend', :state => 'IN')
doc = @klass.new(:foo => address)
doc.save
doc.foo.new?.should == false
end

should "not be new when document is read back" do
address = @address_class.new(:city => 'South Bend', :state => 'IN')
doc = @klass.new(:foo => address)
doc.save

doc = doc.reload
doc.foo.new?.should == false
end
end

should "be able to save" do
person = @klass.create

pet = @pet_klass.new(:name => 'sparky')
person.pets << pet
pet.should be_new
pet.save
pet.should_not be_new

person.reload
person.pets.first.should == pet
end

should "be able to dynamically add new keys and save" do
person = @klass.create

pet = @pet_klass.new(:name => 'sparky', :crazy_key => 'crazy')
person.pets << pet
pet.save

person.reload
person.pets.first.crazy_key.should == 'crazy'
end

should "be able to update_attributes" do
pet = @pet_klass.new(:name => 'sparky')
person = @klass.create(:pets => [pet])
person.reload
pet = person.pets.first

pet.update_attributes(:name => 'koda').should be_true
person.reload
person.pets.first._id.should == pet._id
person.pets.first.name.should == 'koda'
end

should "be able to update_attributes!" do
person = @klass.create(:pets => [@pet_klass.new(:name => 'sparky')])
person.reload
pet = person.pets.first

attributes = {:name => 'koda'}
pet.expects(:attributes=).with(attributes)
pet.expects(:save!)
Expand Down
30 changes: 15 additions & 15 deletions test/unit/test_embedded_document.rb
Expand Up @@ -42,7 +42,7 @@ class ::OtherChild < ::Parent
Object.send :remove_const, 'Child' if defined?(::Child)
Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
end

context "Including MongoMapper::EmbeddedDocument in a class" do
setup do
@klass = EDoc()
Expand Down Expand Up @@ -249,34 +249,34 @@ class ::OtherChild < ::Parent

should "convert string object id to mongo object id when assigning id with _id object id type" do
id = Mongo::ObjectID.new

doc = @document.new(:id => id.to_s)
doc._id.should == id
doc.id.should == id

doc.id.should == id
doc = @document.new(:_id => id.to_s)
doc._id.should == id
doc.id.should == id
doc.id.should == id
end

context "_root_document" do
context "_parent_document" do
should "default to nil" do
@document.new._parent_document.should be_nil
@document.new._root_document.should be_nil
end

should "allow setting when initialized" do
should "set _root_document when setting _parent_document" do
root = Doc().new
doc = @document.new :_root_document => root

doc = @document.new(:_parent_document => root)
doc._parent_document.should be(root)
doc._root_document.should be(root)
end

should "also be set on many embedded documents" do
root = Doc().new
klass = EDoc { many :children }
doc = klass.new(:_root_document => root, :children => [{}])

doc.children.first._root_document.should == root
should "set _root_document when setting _parent_document on embedded many" do
root = Doc().new
klass = EDoc { many :children }
parent = klass.new(:_parent_document => root, :children => [{}])
child = parent.children.first
child._parent_document.should be(parent)
child._root_document.should be(root)
end
end

Expand Down

0 comments on commit f57a3b2

Please sign in to comment.