From dd3df8fb69cf0a0e12290bd8571889abc2e176b7 Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Tue, 30 Mar 2010 20:50:47 +0000 Subject: [PATCH] Adding support for defining cast_as on properties as a Class --- lib/couchrest.rb | 2 +- lib/couchrest/mixins/properties.rb | 12 +++------- lib/couchrest/more/property.rb | 14 +++++++++--- lib/couchrest/more/typecast.rb | 1 + lib/couchrest/validation/auto_validate.rb | 2 +- .../more/casted_extended_doc_spec.rb | 22 ++++++++++++------- spec/couchrest/more/casted_model_spec.rb | 2 +- spec/fixtures/more/card.rb | 4 ++-- 8 files changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/couchrest.rb b/lib/couchrest.rb index e88d5a8..38949db 100644 --- a/lib/couchrest.rb +++ b/lib/couchrest.rb @@ -156,4 +156,4 @@ module CouchRest url end end # class << self -end \ No newline at end of file +end diff --git a/lib/couchrest/mixins/properties.rb b/lib/couchrest/mixins/properties.rb index b860c90..e5dc528 100644 --- a/lib/couchrest/mixins/properties.rb +++ b/lib/couchrest/mixins/properties.rb @@ -50,24 +50,18 @@ module CouchRest # Don't cast the property unless it has a value return unless self[key] if property.type.is_a?(Array) - klass = ::CouchRest.constantize(property.type[0]) + klass = property.type[0] self[key] = [self[key]] unless self[key].is_a?(Array) arr = self[key].collect do |value| value = typecast_value(value, klass, property.init_method) associate_casted_to_parent(value, assigned) value end - # only cast arrays of more complex objects (i.e. not strings) + # allow casted_by calls to be passed up chain by wrapping in CastedArray self[key] = klass != String ? CastedArray.new(arr) : arr self[key].casted_by = self if self[key].respond_to?(:casted_by) else - if property.type.downcase == 'boolean' - klass = TrueClass - else - klass = ::CouchRest.constantize(property.type) - end - - self[key] = typecast_value(self[key], klass, property.init_method) + self[key] = typecast_value(self[key], property.type, property.init_method) associate_casted_to_parent(self[key], assigned) end end diff --git a/lib/couchrest/more/property.rb b/lib/couchrest/more/property.rb index 88ce725..8811170 100644 --- a/lib/couchrest/more/property.rb +++ b/lib/couchrest/more/property.rb @@ -16,11 +16,19 @@ module CouchRest def parse_type(type) if type.nil? - @type = 'String' + @type = String elsif type.is_a?(Array) && type.empty? - @type = ['Object'] + @type = [Object] else - @type = type.is_a?(Array) ? [type.first.to_s] : type.to_s + base_type = type.is_a?(Array) ? type.first : type + if base_type.is_a?(String) + base_type = TrueClass if base_type.downcase == 'boolean' + begin + base_type = ::CouchRest.constantize(base_type) unless base_type.is_a?(Class) + rescue # leave base type as is and convert in more/typecast + end + end + @type = type.is_a?(Array) ? [base_type] : base_type end end diff --git a/lib/couchrest/more/typecast.rb b/lib/couchrest/more/typecast.rb index 497110c..281c572 100644 --- a/lib/couchrest/more/typecast.rb +++ b/lib/couchrest/more/typecast.rb @@ -28,6 +28,7 @@ module CouchRest def typecast_value(value, klass, init_method) return nil if value.nil? + klass = ::CouchRest.constantize(klass) unless klass.is_a?(Class) if value.instance_of?(klass) || klass == Object value elsif [String, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(klass) diff --git a/lib/couchrest/validation/auto_validate.rb b/lib/couchrest/validation/auto_validate.rb index d277bb3..6af1eee 100644 --- a/lib/couchrest/validation/auto_validate.rb +++ b/lib/couchrest/validation/auto_validate.rb @@ -101,7 +101,7 @@ module CouchRest end # length - if property.type == "String" + if property.type == String # XXX: maybe length should always return a Range, with the min defaulting to 1 # 52 being the max set len = property.options.fetch(:length, property.options.fetch(:size, 52)) diff --git a/spec/couchrest/more/casted_extended_doc_spec.rb b/spec/couchrest/more/casted_extended_doc_spec.rb index e92d34f..033e4b4 100644 --- a/spec/couchrest/more/casted_extended_doc_spec.rb +++ b/spec/couchrest/more/casted_extended_doc_spec.rb @@ -1,13 +1,8 @@ require File.expand_path('../../../spec_helper', __FILE__) +require File.join(FIXTURE_PATH, 'more', 'cat') +require File.join(FIXTURE_PATH, 'more', 'person') require File.join(FIXTURE_PATH, 'more', 'card') -class Car < CouchRest::ExtendedDocument - use_database TEST_SERVER.default_database - - property :name - property :driver, :cast_as => 'Driver' -end - class Driver < CouchRest::ExtendedDocument use_database TEST_SERVER.default_database # You have to add a casted_by accessor if you want to reach a casted extended doc parent @@ -16,19 +11,30 @@ class Driver < CouchRest::ExtendedDocument property :name end +class Car < CouchRest::ExtendedDocument + use_database TEST_SERVER.default_database + + property :name + property :driver, :cast_as => 'Driver' + property :backseat_driver, :cast_as => Driver +end + describe "casting an extended document" do before(:each) do @driver = Driver.new(:name => 'Matt') @car = Car.new(:name => 'Renault 306', :driver => @driver) + @car2 = Car.new(:name => 'Renault 306', :backseat_driver => @driver.dup) end it "should retain all properties of the casted attribute" do @car.driver.should == @driver + @car2.backseat_driver.should == @driver end it "should let the casted document know who casted it" do @car.driver.casted_by.should == @car + @car2.backseat_driver.casted_by.should == @car2 end end @@ -70,4 +76,4 @@ describe "casting an extended document from parsed JSON" do it "should retain all properties of the casted attribute" do @new_car.driver.should == @driver end -end \ No newline at end of file +end diff --git a/spec/couchrest/more/casted_model_spec.rb b/spec/couchrest/more/casted_model_spec.rb index 704b85c..0e8c972 100644 --- a/spec/couchrest/more/casted_model_spec.rb +++ b/spec/couchrest/more/casted_model_spec.rb @@ -124,7 +124,7 @@ describe CouchRest::CastedModel do @obj = DummyModel.new(:keywords => ['couch', 'sofa', 'relax', 'canapé']) end - it "should cast the array propery" do + it "should cast the array properly" do @obj.keywords.should be_an_instance_of(Array) @obj.keywords.first.should == 'couch' end diff --git a/spec/fixtures/more/card.rb b/spec/fixtures/more/card.rb index 7365166..999c41f 100644 --- a/spec/fixtures/more/card.rb +++ b/spec/fixtures/more/card.rb @@ -11,7 +11,7 @@ class Card < CouchRest::ExtendedDocument property :first_name property :last_name, :alias => :family_name property :read_only_value, :read_only => true - property :cast_alias, :cast_as => 'Person', :alias => :calias + property :cast_alias, :cast_as => Person, :alias => :calias timestamps! @@ -19,4 +19,4 @@ class Card < CouchRest::ExtendedDocument # Validation validates_presence_of :first_name -end \ No newline at end of file +end