From 42f1ad68655be08a0ff7e5a261d1ad21d3fc90a5 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Tue, 17 May 2011 20:37:11 +0100 Subject: 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. --- .../active_record/associations/collection_association.rb | 8 ++++++-- .../active_record/associations/singular_association.rb | 12 ++++++------ .../cases/associations/has_many_associations_test.rb | 13 +++++++++++++ .../test/cases/associations/has_one_associations_test.rb | 16 ++++++++++++++++ activerecord/test/models/bulb.rb | 13 +++++++++++++ 5 files changed, 54 insertions(+), 8 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 525ac65722..902ad8cb64 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -423,9 +423,13 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb index 877ddf3ee1..44dbe984d4 100644 --- a/activerecord/lib/active_record/associations/singular_association.rb +++ b/activerecord/lib/active_record/associations/singular_association.rb @@ -26,18 +26,18 @@ module ActiveRecord 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 diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 0e33fa9c8e..522ac56d82 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1455,4 +1455,17 @@ class HasManyAssociationsTest < ActiveRecord::TestCase 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 diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 356a4a7a09..38e622f90f 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -410,4 +410,20 @@ class HasOneAssociationsTest < ActiveRecord::TestCase 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 diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb index 7d90963720..0dcc8d5970 100644 --- a/activerecord/test/models/bulb.rb +++ b/activerecord/test/models/bulb.rb @@ -15,4 +15,17 @@ class Bulb < ActiveRecord::Base 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 \ No newline at end of file -- cgit v1.2.3