Skip to content

Commit

Permalink
Pass the attribute and option hashes to build_association
Browse files Browse the repository at this point in the history
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
pixeltrix committed May 17, 2011
1 parent b81f77e commit 42f1ad6
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions activerecord/test/cases/associations/has_many_associations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 16 additions & 0 deletions activerecord/test/cases/associations/has_one_associations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 13 additions & 0 deletions activerecord/test/models/bulb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 42f1ad6

Please sign in to comment.