Skip to content

Commit

Permalink
Has one sets parent before attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
durran committed Jan 13, 2010
1 parent 419fc69 commit d8027e8
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 59 deletions.
1 change: 1 addition & 0 deletions lib/mongoid/associations/has_many.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def build(attrs = {}, type = nil)
object = type ? type.instantiate : @klass.instantiate
object.parentize(@parent, @association_name)
object.write_attributes(attrs)
object.generate_key
@documents << object
object
end
Expand Down
20 changes: 7 additions & 13 deletions lib/mongoid/associations/has_one.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,6 @@ class HasOne #:nodoc:

attr_reader :association_name, :document, :parent, :options

# Build a new object for the association.
def build(attrs = {}, type = nil)
@document = attrs.assimilate(@parent, @options, type)
self
end

# Create a new object for the association and save it.
def create(attrs = {}, type = nil)
build(attrs, type)
@document.save
self
end

# Creates the new association by finding the attributes in
# the parent document with its name, and instantiating a
# new document for it.
Expand Down Expand Up @@ -58,6 +45,13 @@ def valid?
@document.valid?
end

protected
# Build a new object for the association.
def build(attrs = {}, type = nil)
@document = attrs.assimilate(@parent, @options, type)
self
end

class << self
# Preferred method of instantiating a new +HasOne+, since nil values
# will be handled properly.
Expand Down
17 changes: 9 additions & 8 deletions lib/mongoid/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ def clone
self.class.instantiate(@attributes.except(:_id).except(:versions).dup, true)
end

# Generate an id for this +Document+.
def generate_key
if primary_key
@attributes[:_id] = extract_keys.join(" ").identify
else
@attributes[:_id] = Mongo::ObjectID.new.to_s unless id
end
end

# Instantiate a new +Document+, setting the Document's attributes if
# given. If no attributes are provided, they will be initialized with
# an empty +Hash+.
Expand Down Expand Up @@ -269,14 +278,6 @@ def update(child, clear = false)
end

protected
def generate_key
if primary_key
@attributes[:_id] = extract_keys.join(" ").identify
else
@attributes[:_id] = Mongo::ObjectID.new.to_s unless id
end
end

def generate_type
@attributes[:_type] ||= self.class.name
end
Expand Down
5 changes: 4 additions & 1 deletion lib/mongoid/extensions/hash/assimilation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ module Assimilation #:nodoc:
#
# Returns: The child +Document+.
def assimilate(parent, options, type = nil)
child = type ? type.instantiate(self.merge(:_type => type.name)) : options.klass.instantiate(self)
klass = type ? type : options.klass
child = klass.instantiate(:_parent => parent)
child.write_attributes(self.merge(:_type => klass.name))
child.generate_key
child.assimilate(parent, options)
end
end
Expand Down
5 changes: 5 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,13 @@ class Name
include Mongoid::Document
field :first_name
field :last_name
field :parent_title
key :first_name, :last_name
belongs_to :person, :inverse_of => :name

def set_parent=(set = false)
self.parent_title = person.title if set
end
end

class Comment
Expand Down
46 changes: 9 additions & 37 deletions spec/unit/mongoid/associations/has_one_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@document = stub(:attributes => @attributes, :update => true)
end

describe "#build" do
describe "#build_*" do

context "when attributes provided" do

Expand All @@ -23,7 +23,7 @@
end

it "replaces the existing has_one" do
drink = @association.build({ :name => "Sapphire and Tonic" })
drink = @association.send(:build, { :name => "Sapphire and Tonic" })
drink.name.should == "Sapphire and Tonic"
end

Expand All @@ -40,51 +40,23 @@
end

it "instantiates a class of that type" do
writer = @association.build({ :speed => 500 }, HtmlWriter)
writer = @association.send(:build, { :speed => 500 }, HtmlWriter)
writer.should be_a_kind_of(HtmlWriter)
writer.speed.should == 500
end

end

end

describe "#create" do

context "when attributes provided" do
context "setting the parent relationship" do

before do
@association = Mongoid::Associations::HasOne.new(
@document,
@attributes[:mixed_drink],
Mongoid::Associations::Options.new(:name => :mixed_drink)
)
@drink = MixedDrink.new(:name => "Sapphire and Tonic")
@person = Person.new
end

it "replaces and saves the existing has_one" do
Mongoid::Commands::Save.expects(:execute).returns(true)
drink = @association.create({ :name => "Sapphire and Tonic" })
drink.name.should == "Sapphire and Tonic"
end

end

context "when a type is supplied" do

before do
@association = Mongoid::Associations::HasOne.new(
@document,
@attributes[:writer],
Mongoid::Associations::Options.new(:name => :writer)
)
end

it "instantiates a class of that type" do
Mongoid::Commands::Save.expects(:execute).returns(true)
writer = @association.create({ :speed => 500 }, HtmlWriter)
writer.should be_a_kind_of(HtmlWriter)
writer.speed.should == 500
it "happens before any other operation" do
name = @person.build_name(:set_parent => true, :street => "Madison Ave")
name._parent.should == @person
@person.name.should == name
end

end
Expand Down

0 comments on commit d8027e8

Please sign in to comment.