Adding support for defining cast_as on properties as a Class
This commit is contained in:
parent
64d68ecc1a
commit
dd3df8fb69
|
@ -50,24 +50,18 @@ module CouchRest
|
||||||
# Don't cast the property unless it has a value
|
# Don't cast the property unless it has a value
|
||||||
return unless self[key]
|
return unless self[key]
|
||||||
if property.type.is_a?(Array)
|
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)
|
self[key] = [self[key]] unless self[key].is_a?(Array)
|
||||||
arr = self[key].collect do |value|
|
arr = self[key].collect do |value|
|
||||||
value = typecast_value(value, klass, property.init_method)
|
value = typecast_value(value, klass, property.init_method)
|
||||||
associate_casted_to_parent(value, assigned)
|
associate_casted_to_parent(value, assigned)
|
||||||
value
|
value
|
||||||
end
|
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] = klass != String ? CastedArray.new(arr) : arr
|
||||||
self[key].casted_by = self if self[key].respond_to?(:casted_by)
|
self[key].casted_by = self if self[key].respond_to?(:casted_by)
|
||||||
else
|
else
|
||||||
if property.type.downcase == 'boolean'
|
self[key] = typecast_value(self[key], property.type, property.init_method)
|
||||||
klass = TrueClass
|
|
||||||
else
|
|
||||||
klass = ::CouchRest.constantize(property.type)
|
|
||||||
end
|
|
||||||
|
|
||||||
self[key] = typecast_value(self[key], klass, property.init_method)
|
|
||||||
associate_casted_to_parent(self[key], assigned)
|
associate_casted_to_parent(self[key], assigned)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,11 +16,19 @@ module CouchRest
|
||||||
|
|
||||||
def parse_type(type)
|
def parse_type(type)
|
||||||
if type.nil?
|
if type.nil?
|
||||||
@type = 'String'
|
@type = String
|
||||||
elsif type.is_a?(Array) && type.empty?
|
elsif type.is_a?(Array) && type.empty?
|
||||||
@type = ['Object']
|
@type = [Object]
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ module CouchRest
|
||||||
|
|
||||||
def typecast_value(value, klass, init_method)
|
def typecast_value(value, klass, init_method)
|
||||||
return nil if value.nil?
|
return nil if value.nil?
|
||||||
|
klass = ::CouchRest.constantize(klass) unless klass.is_a?(Class)
|
||||||
if value.instance_of?(klass) || klass == Object
|
if value.instance_of?(klass) || klass == Object
|
||||||
value
|
value
|
||||||
elsif [String, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(klass)
|
elsif [String, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class].include?(klass)
|
||||||
|
|
|
@ -101,7 +101,7 @@ module CouchRest
|
||||||
end
|
end
|
||||||
|
|
||||||
# length
|
# length
|
||||||
if property.type == "String"
|
if property.type == String
|
||||||
# XXX: maybe length should always return a Range, with the min defaulting to 1
|
# XXX: maybe length should always return a Range, with the min defaulting to 1
|
||||||
# 52 being the max set
|
# 52 being the max set
|
||||||
len = property.options.fetch(:length, property.options.fetch(:size, 52))
|
len = property.options.fetch(:length, property.options.fetch(:size, 52))
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
require File.expand_path('../../../spec_helper', __FILE__)
|
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')
|
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
|
class Driver < CouchRest::ExtendedDocument
|
||||||
use_database TEST_SERVER.default_database
|
use_database TEST_SERVER.default_database
|
||||||
# You have to add a casted_by accessor if you want to reach a casted extended doc parent
|
# 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
|
property :name
|
||||||
end
|
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
|
describe "casting an extended document" do
|
||||||
|
|
||||||
before(:each) do
|
before(:each) do
|
||||||
@driver = Driver.new(:name => 'Matt')
|
@driver = Driver.new(:name => 'Matt')
|
||||||
@car = Car.new(:name => 'Renault 306', :driver => @driver)
|
@car = Car.new(:name => 'Renault 306', :driver => @driver)
|
||||||
|
@car2 = Car.new(:name => 'Renault 306', :backseat_driver => @driver.dup)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should retain all properties of the casted attribute" do
|
it "should retain all properties of the casted attribute" do
|
||||||
@car.driver.should == @driver
|
@car.driver.should == @driver
|
||||||
|
@car2.backseat_driver.should == @driver
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should let the casted document know who casted it" do
|
it "should let the casted document know who casted it" do
|
||||||
@car.driver.casted_by.should == @car
|
@car.driver.casted_by.should == @car
|
||||||
|
@car2.backseat_driver.casted_by.should == @car2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ describe CouchRest::CastedModel do
|
||||||
@obj = DummyModel.new(:keywords => ['couch', 'sofa', 'relax', 'canapé'])
|
@obj = DummyModel.new(:keywords => ['couch', 'sofa', 'relax', 'canapé'])
|
||||||
end
|
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.should be_an_instance_of(Array)
|
||||||
@obj.keywords.first.should == 'couch'
|
@obj.keywords.first.should == 'couch'
|
||||||
end
|
end
|
||||||
|
|
2
spec/fixtures/more/card.rb
vendored
2
spec/fixtures/more/card.rb
vendored
|
@ -11,7 +11,7 @@ class Card < CouchRest::ExtendedDocument
|
||||||
property :first_name
|
property :first_name
|
||||||
property :last_name, :alias => :family_name
|
property :last_name, :alias => :family_name
|
||||||
property :read_only_value, :read_only => true
|
property :read_only_value, :read_only => true
|
||||||
property :cast_alias, :cast_as => 'Person', :alias => :calias
|
property :cast_alias, :cast_as => Person, :alias => :calias
|
||||||
|
|
||||||
|
|
||||||
timestamps!
|
timestamps!
|
||||||
|
|
Loading…
Reference in a new issue