Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Pass the attribute and option hashes to build_association

The build_association method was added as an API for plugins
to hook into in 1398db0. This commit restores this API and the
ability to override class.new to return a subclass based on
a virtual attribute in the attributes hash.
  • Loading branch information...
commit 42f1ad68655be08a0ff7e5a261d1ad21d3fc90a5 1 parent b81f77e
@pixeltrix pixeltrix authored
View
8 activerecord/lib/active_record/associations/collection_association.rb
@@ -423,9 +423,13 @@ def insert_record(record, validate = true)
raise NotImplementedError
end
+ def create_scope
+ scoped.scope_for_create.stringify_keys
+ end
+
def build_record(attributes, options)
- record = reflection.build_association
- record.assign_attributes(scoped.scope_for_create, :without_protection => true)
+ record = reflection.build_association(attributes, options)
+ record.assign_attributes(create_scope.except(*record.changed), :without_protection => true)
record.assign_attributes(attributes, options)
record
end
View
12 activerecord/lib/active_record/associations/singular_association.rb
@@ -26,18 +26,18 @@ def create!(attributes = {}, options = {})
end
def build(attributes = {}, options = {})
- record = reflection.build_association
- record.assign_attributes(
- scoped.scope_for_create.except(klass.primary_key),
- :without_protection => true
- )
- record.assign_attributes(attributes, options)
+ record = reflection.build_association(attributes, options)
+ record.assign_attributes(create_scope.except(*record.changed), :without_protection => true)
set_new_record(record)
record
end
private
+ def create_scope
+ scoped.scope_for_create.stringify_keys.except(klass.primary_key)
+ end
+
def find_target
scoped.first.tap { |record| set_inverse_instance(record) }
end
View
13 activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1455,4 +1455,17 @@ def test_merging_with_custom_attribute_writer
assert_equal "RED!", car.bulbs.to_a.first.color
end
+
+ def test_new_is_called_with_attributes_and_options
+ car = Car.create(:name => 'honda')
+
+ bulb = car.bulbs.build
+ assert_equal Bulb, bulb.class
+
+ bulb = car.bulbs.build(:bulb_type => :custom)
+ assert_equal Bulb, bulb.class
+
+ bulb = car.bulbs.build({ :bulb_type => :custom }, :as => :admin)
+ assert_equal CustomBulb, bulb.class
+ end
end
View
16 activerecord/test/cases/associations/has_one_associations_test.rb
@@ -410,4 +410,20 @@ def test_association_conditions_bypass_attribute_protection
bulb = car.create_frickinawesome_bulb(:frickinawesome => false)
assert_equal true, bulb.frickinawesome?
end
+
+ def test_new_is_called_with_attributes_and_options
+ car = Car.create(:name => 'honda')
+
+ bulb = car.build_bulb
+ assert_equal Bulb, bulb.class
+
+ bulb = car.build_bulb
+ assert_equal Bulb, bulb.class
+
+ bulb = car.build_bulb(:bulb_type => :custom)
+ assert_equal Bulb, bulb.class
+
+ bulb = car.build_bulb({ :bulb_type => :custom }, :as => :admin)
+ assert_equal CustomBulb, bulb.class
+ end
end
View
13 activerecord/test/models/bulb.rb
@@ -15,4 +15,17 @@ def color=(color)
self[:color] = color.upcase + "!"
end
+ def self.new(attributes = {}, options = {}, &block)
+ bulb_type = (attributes || {}).delete(:bulb_type)
+
+ if options && options[:as] == :admin && bulb_type.present?
+ bulb_class = "#{bulb_type.to_s.camelize}Bulb".constantize
+ bulb_class.new(attributes, options, &block)
+ else
+ super
+ end
+ end
end
+
+class CustomBulb < Bulb
+end
Please sign in to comment.
Something went wrong with that request. Please try again.