diff --git a/lib/couchrest/mixins/properties.rb b/lib/couchrest/mixins/properties.rb index 676f045..ae18323 100644 --- a/lib/couchrest/mixins/properties.rb +++ b/lib/couchrest/mixins/properties.rb @@ -44,13 +44,14 @@ module CouchRest target = property.type if target.is_a?(Array) klass = ::CouchRest.constantize(target[0]) - self[property.name] = self[key].collect do |value| + arr = self[key].collect do |value| # Auto parse Time objects obj = ( (property.init_method == 'new') && klass == Time) ? Time.parse(value) : klass.send(property.init_method, value) obj.casted_by = self if obj.respond_to?(:casted_by) obj.document_saved = true if obj.respond_to?(:document_saved) obj end + self[property.name] = target[0] != 'String' ? CastedArray.new(arr) : arr else # Auto parse Time objects self[property.name] = if ((property.init_method == 'new') && target == 'Time') @@ -63,6 +64,7 @@ module CouchRest self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by) self[property.name].document_saved = true if self[property.name].respond_to?(:document_saved) end + self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by) end end @@ -109,6 +111,14 @@ module CouchRest meth = property.name class_eval <<-EOS def #{meth}=(value) + if #{property.casted} && value.is_a?(Array) + arr = CastedArray.new + arr.casted_by = self + value.each { |v| arr << v } + value = arr + elsif #{property.casted} + value.casted_by = self if value.respond_to?(:casted_by) + end self['#{meth}'] = value end EOS diff --git a/lib/couchrest/more/property.rb b/lib/couchrest/more/property.rb index 77e2b90..dccc7dd 100644 --- a/lib/couchrest/more/property.rb +++ b/lib/couchrest/more/property.rb @@ -38,3 +38,22 @@ module CouchRest end end + +class CastedArray < Array + attr_accessor :casted_by + + def << obj + obj.casted_by = self.casted_by if obj.respond_to?(:casted_by) + super(obj) + end + + def push(obj) + obj.casted_by = self.casted_by if obj.respond_to?(:casted_by) + super(obj) + end + + def []= index, obj + obj.casted_by = self.casted_by if obj.respond_to?(:casted_by) + super(index, obj) + end +end \ No newline at end of file diff --git a/spec/couchrest/more/property_spec.rb b/spec/couchrest/more/property_spec.rb index 146f0f8..57af71a 100644 --- a/spec/couchrest/more/property_spec.rb +++ b/spec/couchrest/more/property_spec.rb @@ -3,6 +3,7 @@ require File.join(FIXTURE_PATH, 'more', 'card') require File.join(FIXTURE_PATH, 'more', 'invoice') require File.join(FIXTURE_PATH, 'more', 'service') require File.join(FIXTURE_PATH, 'more', 'event') +require File.join(FIXTURE_PATH, 'more', 'cat') describe "ExtendedDocument properties" do @@ -131,6 +132,70 @@ describe "ExtendedDocument properties" do @event['occurs_at'].should be_an_instance_of(Time) end end + end +end + +describe "a newly created casted model" do + before(:each) do + reset_test_db! + @cat = Cat.new(:name => 'Toonces') + @squeaky_mouse = CatToy.new(:name => 'Squeaky') end + describe "assigned assigned to a casted property" do + it "should have casted_by set to its parent" do + @squeaky_mouse.casted_by.should be_nil + @cat.favorite_toy = @squeaky_mouse + @squeaky_mouse.casted_by.should === @cat + end + end + + describe "appended to a casted collection" do + it "should have casted_by set to its parent" do + @squeaky_mouse.casted_by.should be_nil + @cat.toys << @squeaky_mouse + @squeaky_mouse.casted_by.should === @cat + @cat.save + @cat.toys.first.casted_by.should === @cat + end + end + + describe "list assigned to a casted collection" do + it "should have casted_by set on all elements" do + toy1 = CatToy.new(:name => 'Feather') + toy2 = CatToy.new(:name => 'Mouse') + @cat.toys = [toy1, toy2] + toy1.casted_by.should === @cat + toy2.casted_by.should === @cat + @cat.save + @cat = Cat.get(@cat.id) + @cat.toys[0].casted_by.should === @cat + @cat.toys[1].casted_by.should === @cat + end + end end + +describe "a casted model retrieved from the database" do + before(:each) do + reset_test_db! + @cat = Cat.new(:name => 'Stimpy') + @cat.favorite_toy = CatToy.new(:name => 'Stinky') + @cat.toys << CatToy.new(:name => 'Feather') + @cat.toys << CatToy.new(:name => 'Mouse') + @cat.save + @cat = Cat.get(@cat.id) + end + + describe "as a casted property" do + it "should already be casted_by its parent" do + @cat.favorite_toy.casted_by.should === @cat + end + end + + describe "from a casted collection" do + it "should already be casted_by its parent" do + @cat.toys[0].casted_by.should === @cat + @cat.toys[1].casted_by.should === @cat + end + end +end \ No newline at end of file