Skip to content

Commit be716a0

Browse files
committed
WIP on Mongoid raw value for mongoize/demongoize
1 parent 67c211d commit be716a0

File tree

23 files changed

+217
-59
lines changed

23 files changed

+217
-59
lines changed

lib/mongoid/attributes.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ def write_attribute(name, value)
170170

171171
if attribute_writable?(field_name)
172172
_assigning do
173+
# TODO: remove this
174+
# validate_attribute_value(field_name, value)
173175
localized = fields[field_name].try(:localized?)
174176
attributes_before_type_cast[name.to_s] = value
175177
typed_value = typed_value_for(field_name, value)
@@ -358,6 +360,31 @@ def unalias_attribute(name)
358360

359361
private
360362

363+
# Validates an attribute value as being assignable to the specified field.
364+
#
365+
# For now, only Hash and Array fields are validated, and the value is
366+
# being checked to be of an appropriate type (i.e. either Hash or Array,
367+
# respectively, or nil).
368+
#
369+
# This method takes the name of the field as stored in the document
370+
# in the database, not (necessarily) the Ruby method name used to read/write
371+
# the said field.
372+
#
373+
# @param [ String, Symbol ] field_name The name of the field.
374+
# @param [ Object ] value The value to be validated.
375+
# TODO: remove this
376+
# def validate_attribute_value(field_name, value)
377+
# return if value.nil?
378+
# field = fields[field_name]
379+
# return unless field
380+
# validatable_types = [ Hash, Array ]
381+
# if validatable_types.include?(field.type)
382+
# unless value.is_a?(field.type)
383+
# raise Mongoid::Errors::InvalidValue.new(field.type, value.class)
384+
# end
385+
# end
386+
# end
387+
361388
def lookup_attribute_presence(name, value)
362389
if localized_fields.has_key?(name) && value
363390
value = localized_fields[name].send(:lookup, value)

lib/mongoid/config.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ module Config
7171
# existing method.
7272
option :scope_overwrite_exception, default: false
7373

74+
# Indicates whether or not to raise an error when attempting
75+
# to assign an incompatible type to a field.
76+
option :strict_type_assignment, default: false
77+
78+
# Indicates whether uncastable values from the database should
79+
# be returned wrapped by Mongoid::RawValue class.
80+
option :wrap_uncastable_values_from_database, default: false
81+
7482
# Use ActiveSupport's time zone in time operations instead of the
7583
# Ruby default time zone.
7684
option :use_activesupport_time_zone, default: true

lib/mongoid/criteria/queryable/extensions/array.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def evolve(object)
137137
when ::Array, ::Set
138138
object.map { |obj| obj.class.evolve(obj) }
139139
else
140-
object
140+
Mongoid::RawValue(object, 'Array')
141141
end
142142
end
143143
end

lib/mongoid/criteria/queryable/selector.rb

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,18 +150,24 @@ def evolve_multi(specs)
150150
#
151151
# @return [ Object ] The serialized object.
152152
def evolve(serializer, value)
153-
case value
154-
when Mongoid::RawValue
155-
value.raw_value
156-
when Hash
157-
evolve_hash(serializer, value)
158-
when Array
159-
evolve_array(serializer, value)
160-
when Range
161-
value.__evolve_range__(serializer: serializer)
162-
else
163-
(serializer || value.class).evolve(value)
153+
_value = case value
154+
when Mongoid::RawValue
155+
value.raw_value
156+
when Hash
157+
evolve_hash(serializer, value)
158+
when Array
159+
evolve_array(serializer, value)
160+
when Range
161+
value.__evolve_range__(serializer: serializer)
162+
else
163+
(serializer || value.class).evolve(value)
164+
end
165+
166+
while _value.is_a?(Mongoid::RawValue) do
167+
_value = _value.raw_value
164168
end
169+
170+
_value
165171
end
166172

167173
# Evolve a single key selection with array values.

lib/mongoid/extensions/array.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ def mongoize(object)
150150
case object
151151
when ::Array, ::Set
152152
object.map(&:mongoize)
153+
else
154+
Mongoid::RawValue(object, 'Array')
153155
end
154156
end
155157

lib/mongoid/extensions/big_decimal.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,18 @@ def mongoize(object)
7070
BSON::Decimal128.new(object)
7171
elsif object.numeric?
7272
BSON::Decimal128.new(object.to_s)
73-
elsif !object.is_a?(String)
74-
object.try(:to_d)
73+
elsif !object.is_a?(String) && object.respond_to?(:to_d)
74+
object.to_d
75+
else
76+
Mongoid::RawValue(object, 'BigDecimal')
7577
end
7678
else
7779
if object.is_a?(BSON::Decimal128) || object.numeric?
7880
object.to_s
79-
elsif !object.is_a?(String)
80-
object.try(:to_d)&.to_s
81+
elsif !object.is_a?(String) && object.respond_to?(:to_d)
82+
object.to_d
83+
else
84+
Mongoid::RawValue(object, 'BigDecimal')
8185
end
8286
end
8387
end

lib/mongoid/extensions/binary.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def mongoize(object)
3030
case object
3131
when BSON::Binary then object
3232
when String, Symbol then BSON::Binary.new(object.to_s)
33+
else Mongoid::RawValue(object, 'BSON::Binary')
3334
end
3435
end
3536
alias :demongoize :mongoize

lib/mongoid/extensions/boolean.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ def mongoize(object)
1818
true
1919
elsif object.to_s =~ (/\A(false|f|no|n|off|0|0.0)\z/i)
2020
false
21+
else
22+
Mongoid::RawValue(object, 'Boolean')
2123
end
2224
end
2325
alias :demongoize :mongoize

lib/mongoid/extensions/date.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ def mongoize(object)
7171
else
7272
time = object.__mongoize_time__
7373
end
74+
75+
if time.acts_like?(:time)
76+
return ::Time.utc(time.year, time.month, time.day)
77+
end
7478
rescue ArgumentError
75-
nil
76-
end
77-
if time.acts_like?(:time)
78-
::Time.utc(time.year, time.month, time.day)
7979
end
80+
Mongoid::RawValue(object, 'Date')
8081
end
8182
end
8283
end

lib/mongoid/extensions/float.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ def mongoize(object)
4141
if object.numeric?
4242
object.to_f
4343
end
44+
elsif object.respond_to?(:to_f)
45+
object.to_f
4446
else
45-
object.try(:to_f)
47+
Mongoid::RawValue(object, 'Float')
4648
end
4749
end
4850
alias :demongoize :mongoize

0 commit comments

Comments
 (0)