Allows you to set all the attributes for a particular mass-assignment security role by passing in a hash of attributes with keys matching the attribute names (which again matches the column names) and the role name using the :as option.
To bypass mass-assignment security you can use the :without_protection => true option.
class User < ActiveRecord::Base attr_accessible :name attr_accessible :name, :is_admin, :as => :admin end user = User.new user.assign_attributes({ :name => 'Josh', :is_admin => true }) user.name # => "Josh" user.is_admin? # => false user = User.new user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin) user.name # => "Josh" user.is_admin? # => true user = User.new user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true) user.name # => "Josh" user.is_admin? # => true
# File lib/active_record/attribute_assignment.rb, line 66 66: def assign_attributes(new_attributes, options = {}) 67: return if new_attributes.blank? 68: 69: attributes = new_attributes.stringify_keys 70: multi_parameter_attributes = [] 71: nested_parameter_attributes = [] 72: @mass_assignment_options = options 73: 74: unless options[:without_protection] 75: attributes = sanitize_for_mass_assignment(attributes, mass_assignment_role) 76: end 77: 78: attributes.each do |k, v| 79: if k.include?("(") 80: multi_parameter_attributes << [ k, v ] 81: elsif respond_to?("#{k}=") 82: if v.is_a?(Hash) 83: nested_parameter_attributes << [ k, v ] 84: else 85: send("#{k}=", v) 86: end 87: else 88: raise(UnknownAttributeError, "unknown attribute: #{k}") 89: end 90: end 91: 92: # assign any deferred nested attributes after the base attributes have been set 93: nested_parameter_attributes.each do |k,v| 94: send("#{k}=", v) 95: end 96: 97: @mass_assignment_options = nil 98: assign_multiparameter_attributes(multi_parameter_attributes) 99: end
Allows you to set all the attributes at once by passing in a hash with keys matching the attribute names (which again matches the column names).
If any attributes are protected by either attr_protected or attr_accessible then only settable attributes will be assigned.
class User < ActiveRecord::Base attr_protected :is_admin end user = User.new user.attributes = { :username => 'Phusion', :is_admin => true } user.username # => "Phusion" user.is_admin? # => false
# File lib/active_record/attribute_assignment.rb, line 33 33: def attributes=(new_attributes) 34: return unless new_attributes.is_a?(Hash) 35: 36: assign_attributes(new_attributes) 37: end
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, f for Float, s for String, and a for Array. 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 120 120: def assign_multiparameter_attributes(pairs) 121: execute_callstack_for_multiparameter_attributes( 122: extract_callstack_for_multiparameter_attributes(pairs) 123: ) 124: end
# File lib/active_record/attribute_assignment.rb, line 134 134: def execute_callstack_for_multiparameter_attributes(callstack) 135: errors = [] 136: callstack.each do |name, values_with_empty_parameters| 137: begin 138: send(name + "=", read_value_from_parameter(name, values_with_empty_parameters)) 139: rescue => ex 140: errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name}", ex, name) 141: end 142: end 143: unless errors.empty? 144: raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes" 145: end 146: end
# File lib/active_record/attribute_assignment.rb, line 197 197: def extract_callstack_for_multiparameter_attributes(pairs) 198: attributes = { } 199: 200: pairs.each do |pair| 201: multiparameter_name, value = pair 202: attribute_name = multiparameter_name.split("(").first 203: attributes[attribute_name] = {} unless attributes.include?(attribute_name) 204: 205: parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value) 206: attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value 207: end 208: 209: attributes 210: end
# File lib/active_record/attribute_assignment.rb, line 193 193: def extract_max_param_for_multiparameter_attributes(values_hash_from_param, upper_cap = 100) 194: [values_hash_from_param.keys.max,upper_cap].min 195: end
# File lib/active_record/attribute_assignment.rb, line 216 216: def find_parameter_position(multiparameter_name) 217: multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i 218: end
# File lib/active_record/attribute_assignment.rb, line 126 126: def instantiate_time_object(name, values) 127: if self.class.send(:create_time_zone_conversion_attribute?, name, column_for_attribute(name)) 128: Time.zone.local(*values) 129: else 130: Time.time_with_datetime_fallback(self.class.default_timezone, *values) 131: end 132: end
# File lib/active_record/attribute_assignment.rb, line 174 174: def read_date_parameter_value(name, values_hash_from_param) 175: return nil if (1..3).any? {|position| values_hash_from_param[position].blank?} 176: set_values = [values_hash_from_param[1], values_hash_from_param[2], values_hash_from_param[3]] 177: begin 178: Date.new(*set_values) 179: rescue ArgumentError # if Date.new raises an exception on an invalid date 180: instantiate_time_object(name, set_values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates 181: end 182: end
# File lib/active_record/attribute_assignment.rb, line 184 184: def read_other_parameter_value(klass, name, values_hash_from_param) 185: max_position = extract_max_param_for_multiparameter_attributes(values_hash_from_param) 186: values = (1..max_position).collect do |position| 187: raise "Missing Parameter" if !values_hash_from_param.has_key?(position) 188: values_hash_from_param[position] 189: end 190: klass.new(*values) 191: end
# File lib/active_record/attribute_assignment.rb, line 161 161: def read_time_parameter_value(name, values_hash_from_param) 162: # If Date bits were not provided, error 163: raise "Missing Parameter" if [1,2,3].any?{|position| !values_hash_from_param.has_key?(position)} 164: max_position = extract_max_param_for_multiparameter_attributes(values_hash_from_param, 6) 165: # If Date bits were provided but blank, then return nil 166: return nil if (1..3).any? {|position| values_hash_from_param[position].blank?} 167: 168: set_values = (1..max_position).collect{|position| values_hash_from_param[position] } 169: # If Time bits are not there, then default to 0 170: (3..5).each {|i| set_values[i] = set_values[i].blank? ? 0 : set_values[i]} 171: instantiate_time_object(name, set_values) 172: end
# File lib/active_record/attribute_assignment.rb, line 148 148: def read_value_from_parameter(name, values_hash_from_param) 149: klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass 150: if values_hash_from_param.values.all?{|v|v.nil?} 151: nil 152: elsif klass == Time 153: read_time_parameter_value(name, values_hash_from_param) 154: elsif klass == Date 155: read_date_parameter_value(name, values_hash_from_param) 156: else 157: read_other_parameter_value(klass, name, values_hash_from_param) 158: end 159: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.