Permalink
Browse files

Integrate with Virtus Coercion system (WIP)

  • Loading branch information...
1 parent 92d0588 commit ea82393412202d6dd58589a831617b6a556115ec @solnic solnic committed Sep 11, 2011
Showing with 93 additions and 340 deletions.
  1. +8 −3 lib/dm-core.rb
  2. +10 −11 lib/dm-core/property.rb
  3. +1 −0 lib/dm-core/property/binary.rb
  4. +2 −19 lib/dm-core/property/boolean.rb
  5. +6 −11 lib/dm-core/property/class.rb
  6. +2 −37 lib/dm-core/property/date.rb
  7. +2 −36 lib/dm-core/property/date_time.rb
  8. +3 −18 lib/dm-core/property/decimal.rb
  9. +1 −1 lib/dm-core/property/discriminator.rb
  10. +2 −15 lib/dm-core/property/float.rb
  11. +3 −14 lib/dm-core/property/integer.rb
  12. +5 −4 lib/dm-core/property/lookup.rb
  13. +2 −3 lib/dm-core/property/numeric.rb
  14. +2 −1 lib/dm-core/property/object.rb
  15. +2 −2 lib/dm-core/property/serial.rb
  16. +3 −14 lib/dm-core/property/string.rb
  17. +2 −5 lib/dm-core/property/text.rb
  18. +2 −38 lib/dm-core/property/time.rb
  19. +0 −32 lib/dm-core/property/typecast/numeric.rb
  20. +0 −33 lib/dm-core/property/typecast/time.rb
  21. +0 −8 lib/dm-core/spec/shared/semipublic/property_spec.rb
  22. +1 −1 spec/public/property/binary_spec.rb
  23. +1 −1 spec/public/property/boolean_spec.rb
  24. +1 −1 spec/public/property/class_spec.rb
  25. +1 −1 spec/public/property/date_spec.rb
  26. +1 −1 spec/public/property/date_time_spec.rb
  27. +1 −1 spec/public/property/decimal_spec.rb
  28. +1 −1 spec/public/property/float_spec.rb
  29. +1 −1 spec/public/property/integer_spec.rb
  30. +1 −1 spec/public/property/serial_spec.rb
  31. +1 −1 spec/public/property/string_spec.rb
  32. +1 −1 spec/public/property/text_spec.rb
  33. +1 −1 spec/public/property/time_spec.rb
  34. +1 −1 spec/semipublic/property/boolean_spec.rb
  35. +1 −1 spec/semipublic/property/class_spec.rb
  36. +4 −4 spec/semipublic/property/date_spec.rb
  37. +7 −7 spec/semipublic/property/date_time_spec.rb
  38. +1 −1 spec/semipublic/property/decimal_spec.rb
  39. +1 −1 spec/semipublic/property/float_spec.rb
  40. +1 −1 spec/semipublic/property/integer_spec.rb
  41. +7 −7 spec/semipublic/property/time_spec.rb
View
@@ -1,5 +1,4 @@
require 'addressable/uri'
-require 'virtus'
require 'bigdecimal'
require 'bigdecimal/util'
require 'date'
@@ -12,6 +11,14 @@ module DataMapper
module Undefined; end
end
+require 'virtus'
+
+class Virtus::Coercion::Object
+ def self.to_string(value)
+ value.to_s
+ end
+end
+
require 'dm-core/support/ext/blank'
require 'dm-core/support/ext/hash'
require 'dm-core/support/ext/object'
@@ -62,8 +69,6 @@ module Undefined; end
require 'dm-core/resource/persistence_state/dirty'
require 'dm-core/property'
-require 'dm-core/property/typecast/numeric'
-require 'dm-core/property/typecast/time'
require 'dm-core/property/object'
require 'dm-core/property/string'
require 'dm-core/property/binary'
View
@@ -319,7 +319,7 @@ class Property
].to_set.freeze
OPTIONS = [
- :load_as, :dump_as,
+ :load_as, :dump_as, :coercion_method,
:accessor, :reader, :writer,
:lazy, :default, :key, :field,
:index, :unique_index,
@@ -335,7 +335,8 @@ class Property
Query::OPTIONS.to_a
).map { |name| name.to_s }
- attr_reader :load_as, :dump_as, :model, :name, :instance_variable_name,
+ attr_reader :load_as, :dump_as, :coercion_method,
+ :model, :name, :instance_variable_name,
:reader_visibility, :writer_visibility, :options,
:default, :repository_name, :allow_nil, :allow_blank, :required
@@ -668,11 +669,7 @@ def properties
# @api semipublic
def typecast(value)
- if value.nil? || value_loaded?(value)
- value
- elsif respond_to?(:typecast_to_primitive)
- typecast_to_primitive(value)
- end
+ Virtus::Coercion[value.class].send(coercion_method, value)
end
# Test the value to see if it is a valid value for this Property
@@ -753,11 +750,13 @@ def initialize(model, name, options = {})
@name = name.to_s.chomp('?').to_sym
@options = predefined_options.merge(options).freeze
@instance_variable_name = "@#{@name}".freeze
+ @coercion_method = @options.fetch(:coercion_method)
+
+ @load_as = self.class.load_as
+ @dump_as = @options.fetch(:dump_as, @load_as)
- @load_as = self.class.load_as
- @dump_as = @options.fetch(:dump_as, @load_as)
- @field = @options[:field].freeze unless @options[:field].nil?
- @default = @options[:default]
+ @field = @options[:field].freeze unless @options[:field].nil?
+ @default = @options[:default]
@serial = @options.fetch(:serial, false)
@key = @options.fetch(:key, @serial)
@@ -1,6 +1,7 @@
module DataMapper
class Property
class Binary < String
+
end # class Binary
end # class Property
end # module DataMapper
@@ -1,30 +1,13 @@
module DataMapper
class Property
class Boolean < Object
- load_as ::TrueClass
-
- TRUE_VALUES = [ 1, '1', 't', 'T', 'true', 'TRUE' ].freeze
- FALSE_VALUES = [ 0, '0', 'f', 'F', 'false', 'FALSE' ].freeze
- BOOLEAN_MAP = Hash[
- TRUE_VALUES.product([ true ]) + FALSE_VALUES.product([ false ]) ].freeze
+ load_as ::TrueClass
+ coercion_method :to_boolean
# @api semipublic
def value_dumped?(value)
value == true || value == false
end
-
- # Typecast a value to a true or false
- #
- # @param [Integer, #to_str] value
- # value to typecast
- #
- # @return [Boolean]
- # true or false constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
- BOOLEAN_MAP.fetch(value, value)
- end
end # class Boolean
end # class Property
end # module DataMapper
@@ -1,22 +1,17 @@
module DataMapper
class Property
class Class < Object
- load_as ::Class
+ load_as ::Class
+ coercion_method :to_constant
- # Typecast a value to a Class
- #
- # @param [#to_s] value
- # value to typecast
- #
- # @return [Class]
- # Class constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
+ # @api semipublic
+ def typecast(value)
+ return unless value
DataMapper::Ext::Module.find_const(model, value.to_s)
rescue NameError
value
end
+
end # class Class
end # class Property
end # module DataMapper
@@ -1,44 +1,9 @@
module DataMapper
class Property
class Date < Object
- include Typecast::Time
+ load_as ::Date
+ coercion_method :to_date
- load_as ::Date
-
- # Typecasts an arbitrary value to a Date
- # Handles both Hashes and Date instances.
- #
- # @param [Hash, #to_mash, #to_s] value
- # value to be typecast
- #
- # @return [Date]
- # Date constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
- if value.respond_to?(:to_date)
- value.to_date
- elsif value.is_a?(::Hash) || value.respond_to?(:to_mash)
- typecast_hash_to_date(value)
- else
- ::Date.parse(value.to_s)
- end
- rescue ArgumentError
- value
- end
-
- # Creates a Date instance from a Hash with keys :year, :month, :day
- #
- # @param [Hash, #to_mash] value
- # value to be typecast
- #
- # @return [Date]
- # Date constructed from hash
- #
- # @api private
- def typecast_hash_to_date(value)
- ::Date.new(*extract_time(value)[0, 3])
- end
end # class Date
end # class Property
end # module DataMapper
@@ -1,43 +1,9 @@
module DataMapper
class Property
class DateTime < Object
- include Typecast::Time
+ load_as ::DateTime
+ coercion_method :to_datetime
- load_as ::DateTime
-
- # Typecasts an arbitrary value to a DateTime.
- # Handles both Hashes and DateTime instances.
- #
- # @param [Hash, #to_mash, #to_s] value
- # value to be typecast
- #
- # @return [DateTime]
- # DateTime constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
- if value.is_a?(::Hash) || value.respond_to?(:to_mash)
- typecast_hash_to_datetime(value)
- else
- ::DateTime.parse(value.to_s)
- end
- rescue ArgumentError
- value
- end
-
- # Creates a DateTime instance from a Hash with keys :year, :month, :day,
- # :hour, :min, :sec
- #
- # @param [Hash, #to_mash] value
- # value to be typecast
- #
- # @return [DateTime]
- # DateTime constructed from hash
- #
- # @api private
- def typecast_hash_to_datetime(value)
- ::DateTime.new(*extract_time(value))
- end
end # class DateTime
end # class Property
end # module DataMapper
@@ -1,15 +1,16 @@
module DataMapper
class Property
class Decimal < Numeric
- load_as BigDecimal
+ load_as BigDecimal
+ coercion_method :to_decimal
DEFAULT_PRECISION = 10
DEFAULT_SCALE = 0
precision(DEFAULT_PRECISION)
scale(DEFAULT_SCALE)
- protected
+ protected
def initialize(model, name, options = {})
super
@@ -29,22 +30,6 @@ def initialize(model, name, options = {})
end
end
- # Typecast a value to a BigDecimal
- #
- # @param [#to_str, #to_d, Integer] value
- # value to typecast
- #
- # @return [BigDecimal]
- # BigDecimal constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
- if value.kind_of?(::Integer)
- value.to_s.to_d
- else
- typecast_to_numeric(value, :to_d)
- end
- end
end # class Decimal
end # class Property
end # module DataMapper
@@ -20,7 +20,7 @@ def new(*args, &block)
discriminator = properties(repository_name).discriminator
if discriminator_value = args.first[discriminator.name]
- model = discriminator.typecast_to_primitive(discriminator_value)
+ model = discriminator.typecast(discriminator_value)
if model.kind_of?(Model) && !model.equal?(self)
return model.new(*args, &block)
@@ -1,28 +1,15 @@
module DataMapper
class Property
class Float < Numeric
- load_as ::Float
+ load_as ::Float
+ coercion_method :to_float
DEFAULT_PRECISION = 10
DEFAULT_SCALE = nil
precision(DEFAULT_PRECISION)
scale(DEFAULT_SCALE)
- protected
-
- # Typecast a value to a Float
- #
- # @param [#to_str, #to_f] value
- # value to typecast
- #
- # @return [Float]
- # Float constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
- typecast_to_numeric(value, :to_f)
- end
end # class Float
end # class Property
end # module DataMapper
@@ -1,11 +1,12 @@
module DataMapper
class Property
class Integer < Numeric
- load_as ::Integer
+ load_as ::Integer
+ coercion_method :to_integer
accept_options :serial
- protected
+ protected
# @api semipublic
def initialize(model, name, options = {})
@@ -15,18 +16,6 @@ def initialize(model, name, options = {})
super
end
- # Typecast a value to an Integer
- #
- # @param [#to_str, #to_i] value
- # value to typecast
- #
- # @return [Integer]
- # Integer constructed from value
- #
- # @api private
- def typecast_to_primitive(value)
- typecast_to_numeric(value, :to_i)
- end
end # class Integer
end # class Property
end # module DataMapper
@@ -2,7 +2,7 @@ module DataMapper
class Property
module Lookup
- protected
+ protected
#
# Provides transparent access to the Properties defined in
@@ -24,6 +24,7 @@ module Lookup
def const_missing(name)
Property.find_class(name.to_s) || super
end
- end
- end
-end
+
+ end # module Lookup
+ end # class Property
+end # module DataMapper
@@ -1,15 +1,14 @@
module DataMapper
class Property
class Numeric < Object
- include Typecast::Numeric
-
accept_options :precision, :scale, :min, :max
+
attr_reader :precision, :scale, :min, :max
DEFAULT_NUMERIC_MIN = 0
DEFAULT_NUMERIC_MAX = 2**31-1
- protected
+ protected
def initialize(model, name, options = {})
super
Oops, something went wrong.

0 comments on commit ea82393

Please sign in to comment.