module ActiveRecord::AttributeAssignment - activerecord-4.2.5.2 Documentation

# module ActiveRecord::AttributeAssignment

### Public Instance Methods

assign_attributes(new_attributes) click to toggle source

Allows you to set all the attributes by passing in a hash of attributes with keys matching the attribute names (which again matches the column names).

If the passed hash responds to `permitted?` method and the return value of this method is `false` an `ActiveModel::ForbiddenAttributesError` exception is raised.

    cat = Cat.new(name: "Gorby", status: "yawning")
    cat.attributes # =>  { "name" => "Gorby", "status" => "yawning", "created_at" => nil, "updated_at" => nil}
    cat.assign_attributes(status: "sleeping")
    cat.attributes # =>  { "name" => "Gorby", "status" => "sleeping", "created_at" => nil, "updated_at" => nil }

New attributes will be persisted in the database when the object is saved.

Aliased to `attributes=`.

    # File lib/active_record/attribute_assignment.rb, line 23
    def assign_attributes(new_attributes)
      if !new_attributes.respond_to?(:stringify_keys)
        raise ArgumentError, "When assigning attributes, you must pass a hash as an argument."
      end
      return if new_attributes.blank?

      attributes                  = new_attributes.stringify_keys
      multi_parameter_attributes  = []
      nested_parameter_attributes = []

      attributes = sanitize_for_mass_assignment(attributes)

      attributes.each do |k, v|
        if k.include?("(")
          multi_parameter_attributes << [ k, v ]
        elsif v.is_a?(Hash)
          nested_parameter_attributes << [ k, v ]
        else
          _assign_attribute(k, v)
        end
      end

      assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
      assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
    end

Also aliased as: attributes=
attributes=(new_attributes)
Alias for: assign_attributes

### Private Instance Methods

_assign_attribute(k, v) click to toggle source

    # File lib/active_record/attribute_assignment.rb, line 53
    def _assign_attribute(k, v)
      public_send("#{k}=", v)
    rescue NoMethodError, NameError
      if respond_to?("#{k}=")
        raise
      else
        raise UnknownAttributeError.new(self, k)
      end
    end

assign_multiparameter_attributes(pairs) click to toggle source

Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done by calling new on the column type or aggregation type (through composed_of) object with these parameters. So having the pairs written_on(1) = “2004”, written_on(2) = “6”, written_on(3) = “24”, will instantiate written_on (a date type) with Date.new(“2004”, “6”, “24”). You can also specify a typecast character in the parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum and f for Float. If all the values for a given attribute are empty, the attribute will be set to `nil`.

    # File lib/active_record/attribute_assignment.rb, line 74
    def assign_multiparameter_attributes(pairs)
      execute_callstack_for_multiparameter_attributes(
        extract_callstack_for_multiparameter_attributes(pairs)
      )
    end

assign_nested_parameter_attributes(pairs) click to toggle source

Assign any deferred nested attributes after the base attributes have been set.

    # File lib/active_record/attribute_assignment.rb, line 64
    def assign_nested_parameter_attributes(pairs)
      pairs.each { |k, v| _assign_attribute(k, v) }
    end

execute_callstack_for_multiparameter_attributes(callstack) click to toggle source

    # File lib/active_record/attribute_assignment.rb, line 80
    def execute_callstack_for_multiparameter_attributes(callstack)
      errors = []
      callstack.each do |name, values_with_empty_parameters|
        begin
          send("#{name}=", MultiparameterAttribute.new(self, name, values_with_empty_parameters).read_value)
        rescue => ex
          errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
        end
      end
      unless errors.empty?
        error_descriptions = errors.map { |ex| ex.message }.join(",")
        raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
      end
    end

extract_callstack_for_multiparameter_attributes(pairs) click to toggle source

    # File lib/active_record/attribute_assignment.rb, line 95
    def extract_callstack_for_multiparameter_attributes(pairs)
      attributes = {}

      pairs.each do |(multiparameter_name, value)|
        attribute_name = multiparameter_name.split("(").first
        attributes[attribute_name] ||= {}

        parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
        attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
      end

      attributes
    end

find_parameter_position(multiparameter_name) click to toggle source

    # File lib/active_record/attribute_assignment.rb, line 113
    def find_parameter_position(multiparameter_name)
      multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
    end

type_cast_attribute_value(multiparameter_name, value) click to toggle source

    # File lib/active_record/attribute_assignment.rb, line 109
    def type_cast_attribute_value(multiparameter_name, value)
      multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
    end