Adding support for defining cast_as on properties as a Class
This commit is contained in:
parent
64d68ecc1a
commit
dd3df8fb69
8 changed files with 34 additions and 25 deletions
|
@ -156,4 +156,4 @@ module CouchRest
|
|||
url
|
||||
end
|
||||
end # class << self
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
4
spec/fixtures/more/card.rb
vendored
4
spec/fixtures/more/card.rb
vendored
|
@ -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
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue