Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

105 lines (91 sloc) 3.563 kb
# encoding: utf-8
module Mongoid
# Adds Rails' multi-parameter attribute support to Mongoid.
#
# @todo: Durran: This module needs an overhaul.
module MultiParameterAttributes
module Errors
# Raised when an error occurred while doing a mass assignment to an
# attribute through the <tt>attributes=</tt> method. The exception
# has an +attribute+ property that is the name of the offending attribute.
class AttributeAssignmentError < Mongoid::Errors::MongoidError
attr_reader :exception, :attribute
def initialize(message, exception, attribute)
@exception = exception
@attribute = attribute
@message = message
end
end
# Raised when there are multiple errors while doing a mass assignment
# through the +attributes+ method. The exception has an +errors+
# property that contains an array of AttributeAssignmentError
# objects, each corresponding to the error while assigning to an
# attribute.
class MultiparameterAssignmentErrors < Mongoid::Errors::MongoidError
attr_reader :errors
def initialize(errors)
@errors = errors
end
end
end
# Process the provided attributes casting them to their proper values if a
# field exists for them on the document. This will be limited to only the
# attributes provided in the suppied +Hash+ so that no extra nil values get
# put into the document's attributes.
#
# @example Process the attributes.
# person.process_attributes(:title => "sir", :age => 40)
#
# @param [ Hash ] attrs The attributes to set.
# @param [ Symbol ] role A role for scoped mass assignment.
# @param [ Boolean ] guard_protected_attributes False to skip mass assignment protection.
#
# @since 2.0.0.rc.7
def process_attributes(attrs = nil, role = :default, guard_protected_attributes = true)
if attrs
errors = []
attributes = {}
multi_parameter_attributes = {}
attrs.each_pair do |key, value|
if key =~ /\A([^\(]+)\((\d+)([if])\)$/
key, index = $1, $2.to_i
(multi_parameter_attributes[key] ||= {})[index] = value.empty? ? nil : value.send("to_#{$3}")
else
attributes[key] = value
end
end
multi_parameter_attributes.each_pair do |key, values|
begin
values = (values.keys.min..values.keys.max).map { |i| values[i] }
field = self.class.fields[aliased_fields[key] || key]
attributes[key] = instantiate_object(field, values)
rescue => e
errors << Errors::AttributeAssignmentError.new(
"error on assignment #{values.inspect} to #{key}", e, key
)
end
end
unless errors.empty?
raise Errors::MultiparameterAssignmentErrors.new(errors),
"#{errors.size} error(s) on assignment of multiparameter attributes"
end
super attributes, role, guard_protected_attributes
else
super
end
end
protected
def instantiate_object(field, values_with_empty_parameters)
return nil if values_with_empty_parameters.all? { |v| v.nil? }
values = values_with_empty_parameters.collect { |v| v.nil? ? 1 : v }
klass = field.type
if klass == DateTime || klass == Date || klass == Time
field.mongoize(values)
elsif klass
klass.new(*values)
else
values
end
end
end
end
Jump to Line
Something went wrong with that request. Please try again.