diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index a03d1bbb06..70c8e75e20 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1533,10 +1533,10 @@ module ActiveRecord def association_constructor_methods(reflection) constructors = { - "build_#{reflection.name}" => "build", - "create_#{reflection.name}" => "create" + "build_#{reflection.name}" => "build", + "create_#{reflection.name}" => "create", + "create_#{reflection.name}!" => "create!" } - constructors["create_#{reflection.name}!"] = "create!" if reflection.macro == :has_one constructors.each do |name, proxy_name| redefine_method(name) do |*params| diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index b5545f4084..d311b0c572 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -6,6 +6,10 @@ module ActiveRecord replace(@reflection.create_association(attributes)) end + def create!(attributes = {}) + build(attributes).tap { |record| record.save! } + end + def build(attributes = {}) replace(@reflection.build_association(attributes)) end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 4c4891dcaf..ef6c482f67 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -120,6 +120,23 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal apple.name, client.firm_name end + def test_create! + client = Client.create!(:name => "Jimmy") + account = client.create_account!(:credit_limit => 10) + assert_equal account, client.account + assert account.persisted? + client.save + client.reload + assert_equal account, client.account + end + + def test_failing_create! + client = Client.create!(:name => "Jimmy") + assert_raise(ActiveRecord::RecordInvalid) { client.create_account! } + assert_not_nil client.account + assert client.account.new_record? + end + def test_natural_assignment_to_nil client = Client.find(3) client.firm = nil diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index f6e7a5ccf7..e8a126fb28 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -124,6 +124,7 @@ class Client < Company belongs_to :firm_with_primary_key_symbols, :class_name => "Firm", :primary_key => :name, :foreign_key => :firm_name belongs_to :readonly_firm, :class_name => "Firm", :foreign_key => "firm_id", :readonly => true has_many :accounts, :through => :firm + belongs_to :account # Record destruction so we can test whether firm.clients.clear has # is calling client.destroy, deleting from the database, or setting diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 7f366b2c91..5f9bb7ee41 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -154,6 +154,7 @@ ActiveRecord::Schema.define do t.string :name t.integer :client_of t.integer :rating, :default => 1 + t.integer :account_id end add_index :companies, [:firm_id, :type, :rating, :ruby_type], :name => "company_index"