Fixing CastedModel bug that modified casted objects

Also refactored code for skipping casting of nil-valued properties
Added and re-arranged specs
This commit is contained in:
Eric Watson 2009-05-25 11:16:48 -05:00 committed by Matt Aimonetti
parent 101024aabc
commit 96f8d1aa96
2 changed files with 45 additions and 10 deletions

View file

@ -39,9 +39,10 @@ module CouchRest
self.class.properties.each do |property| self.class.properties.each do |property|
next unless property.casted next unless property.casted
key = self.has_key?(property.name) ? property.name : property.name.to_sym key = self.has_key?(property.name) ? property.name : property.name.to_sym
# Don't cast the property unless it has a value
next unless self[key]
target = property.type target = property.type
if target.is_a?(Array) if target.is_a?(Array)
next unless self[key]
klass = ::CouchRest.constantize(target[0]) klass = ::CouchRest.constantize(target[0])
self[property.name] = self[key].collect do |value| self[property.name] = self[key].collect do |value|
# Auto parse Time objects # Auto parse Time objects
@ -56,8 +57,7 @@ module CouchRest
else else
# Let people use :send as a Time parse arg # Let people use :send as a Time parse arg
klass = ::CouchRest.constantize(target) klass = ::CouchRest.constantize(target)
# Only cast this key if it has a value. Otherwise, leave nil. klass.send(property.init_method, self[key].dup)
self[key].nil? ? nil : klass.send(property.init_method, self[key])
end end
self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by) self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by)
end end

View file

@ -18,23 +18,58 @@ end
describe "casting an extended document" do describe "casting an extended document" do
before(:each) do
@driver = Driver.new(:name => 'Matt')
@car = Car.new(:name => 'Renault 306', :driver => @driver)
end
it "should retain all properties of the casted attribute" do
@car.driver.should == @driver
end
it "should let the casted document know who casted it" do
@car.driver.casted_by.should == @car
end
end
describe "assigning a value to casted attribute after initializing an object" do
before(:each) do before(:each) do
@car = Car.new(:name => 'Renault 306') @car = Car.new(:name => 'Renault 306')
@driver = Driver.new(:name => 'Matt') @driver = Driver.new(:name => 'Matt')
end end
# it "should not create an empty casted object" do it "should not create an empty casted object" do
# @car.driver.should be_nil @car.driver.should be_nil
# end end
it "should let you assign the casted attribute after instantializing an object" do # Note that this isn't casting the attribute, it's just assigning it a value
# (see "should not cast attribute")
it "should let you assign the value" do
@car.driver = @driver @car.driver = @driver
@car.driver.name.should == 'Matt' @car.driver.name.should == 'Matt'
end end
it "should let the casted document who casted it" do it "should not cast attribute" do
Car.new(:name => 'Renault 306', :driver => @driver) @car.driver = JSON.parse(JSON.generate(@driver))
@car.driver.casted_by.should == @car @car.driver.should_not be_instance_of(Driver)
end end
end end
describe "casting an extended document from parsed JSON" do
before(:each) do
@driver = Driver.new(:name => 'Matt')
@car = Car.new(:name => 'Renault 306', :driver => @driver)
@new_car = Car.new(JSON.parse(JSON.generate(@car)))
end
it "should cast casted attribute" do
@new_car.driver.should be_instance_of(Driver)
end
it "should retain all properties of the casted attribute" do
@new_car.driver.should == @driver
end
end