Created
October 18, 2010 11:31
-
-
Save mataki/632068 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Security pacth for Rails 2.3.9 | |
# put this file on ROOT/config/initializers | |
# http://weblog.rubyonrails.org/2010/10/15/security-vulnerability-in-nested-attributes-code-in-ruby-on-rails-2-3-9-and-3-0-0 | |
# http://weblog.rubyonrails.org/assets/2010/10/15/2-3-nested_attributes.patch | |
module ActiveRecord | |
module NestedAttributes #:nodoc: | |
def assign_nested_attributes_for_one_to_one_association(association_name, attributes) | |
options = nested_attributes_options[association_name] | |
attributes = attributes.with_indifferent_access | |
check_existing_record = (options[:update_only] || !attributes['id'].blank?) | |
if check_existing_record && (record = send(association_name)) && | |
(options[:update_only] || record.id.to_s == attributes['id'].to_s) | |
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) | |
elsif attributes['id'] | |
raise_nested_attributes_record_not_found(association_name, attributes['id']) | |
elsif !reject_new_record?(association_name, attributes) | |
method = "build_#{association_name}" | |
if respond_to?(method) | |
send(method, attributes.except(*UNASSIGNABLE_KEYS)) | |
else | |
raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?" | |
end | |
end | |
end | |
def assign_nested_attributes_for_collection_association(association_name, attributes_collection) | |
options = nested_attributes_options[association_name] | |
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array) | |
raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})" | |
end | |
if options[:limit] && attributes_collection.size > options[:limit] | |
raise TooManyRecords, "Maximum #{options[:limit]} records are allowed. Got #{attributes_collection.size} records instead." | |
end | |
if attributes_collection.is_a? Hash | |
attributes_collection = attributes_collection.sort_by { |index, _| index.to_i }.map { |_, attributes| attributes } | |
end | |
association = send(association_name) | |
existing_records = if association.loaded? | |
association.to_a | |
else | |
attribute_ids = attributes_collection.map {|a| a['id'] || a[:id] }.compact | |
attribute_ids.present? ? association.all(:conditions => {association.primary_key => attribute_ids}) : [] | |
end | |
attributes_collection.each do |attributes| | |
attributes = attributes.with_indifferent_access | |
if attributes['id'].blank? | |
unless reject_new_record?(association_name, attributes) | |
association.build(attributes.except(*UNASSIGNABLE_KEYS)) | |
end | |
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s } | |
association.send(:add_record_to_target_with_callbacks, existing_record) unless association.loaded? | |
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy]) | |
else | |
raise_nested_attributes_record_not_found(association_name, attributes['id']) | |
end | |
end | |
end | |
def raise_nested_attributes_record_not_found(association_name, record_id) | |
reflection = self.class.reflect_on_association(association_name) | |
raise RecordNotFound, "Couldn't find #{reflection.klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment