Module: ActiveModelSerializerPlus::Assignment

Defined in:
lib/active_model_serializer_plus/assignment.rb

Overview

Default implementation of the #attributes= method for ActiveModel classes.

This is the base of the JSON and Xml modules. It supplies a standard #attributes= method to classes that follows the basic pattern of the custom one you’d normally write and adds the ability to pick up object type information from the #attributes_types hash to convert the hash values of contained objects into actual objects. This mostly eliminates the need to write custom #attributes= methods for each class with code to check attribute names and initialize objects from child hashes.

The standard ActiveModel/ActiveRecord serialization/deserialization has some flaws, for instance it will serialize classes as contained hashes whether or not they have an #attributes= method available to deserialize them. We work around that by having building Procs which can do the correct thing in many cases.

Author:

Instance Method Summary collapse

Instance Method Details

#attributes=(hash) ⇒ self

The default #attributes= method which assigns a hash to the object’s attributes.

Parameters:

  • hash (Hash)

    the hash of attribute names and values

Returns:

  • (self)

    self

Raises:

  • (ArgumentError)

    if a value from the @attribute_types hash can’t be converted to a Class



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/active_model_serializer_plus/assignment.rb', line 25

def attributes=(hash)
    hash.each do |key, value|
        # Check #attribute_types for what type this item should be, and if we have an entry
        # convert it to an actual Class object we can use.
        klass = nil
        v = nil
        v = self.attribute_types[key] if self.respond_to?(:attribute_types) && self.attribute_types.is_a?(Hash)
        begin
            klass = ActiveModelSerializerPlus.to_class(v) unless v.nil?
        rescue ArgumentError
            raise ArgumentError, "Type #{v.to_s} for attribute #{key.to_s} is not a valid type."
        end

        unless klass.nil?
            if value.is_a?(Hash)
                # If we're looking at a contained object (our value is a hash), see if we have a Proc
                # to build the object from a hash. If we don't, fall back to creating an object and
                # using the hash #attributes= method if possible. If all else fails just leave the value
                v = ActiveModelSerializerPlus.build(klass.name, value)
                if v.nil? && klass.method_defined?('attributes=')
                    v = klass.new
                    v.attributes = value
                end
                value = v unless v.nil?
            elsif value.is_a?(String)
                v = ActiveModelSerializerPlus.parse(klass.name, value)
                value = v if v
            end
        end

        self.send("#{key}=", value)
    end

    self

end