Skip to content

Commit 00de173

Browse files
committed
Include record in ActiveRecord::RecordNotSaved
Include the relation required to be saved in the `ActiveRecord::RecordNotSaved` exception raised when saving an association that requires the record to be saved. Example: ```ruby class Post < ApplicationRecord has_many :comments validates :title, presence: true end class Comment < ApplicationRecord belongs_to :post end ``` * Before the fix ``` ruby >> post = Post.new(title: :foo) => #<Post id: nil, title: "foo", body: nil, created_at: nil, updated_at: nil> >> post.comments.create! Traceback (most recent call last): 1: from (irb):2 ActiveRecord::RecordNotSaved (You cannot call create unless the parent is saved) >> e = _ => #<ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved> >> e.record => nil ``` * After the fix ```ruby >> post = Post.new(title: :foo) => #<Post id: nil, title: "foo", body: nil, created_at: nil, updated_at: nil> >> post.comments.create! Traceback (most recent call last): 1: from (irb):2 ActiveRecord::RecordNotSaved (You cannot call create unless the parent is saved) >> e = _ => #<ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved> >> e.record => #<Post id: nil, title: "foo", body: nil, created_at: nil, updated_at: nil> ```
1 parent 5f94ea0 commit 00de173

File tree

4 files changed

+19
-8
lines changed

4 files changed

+19
-8
lines changed

activerecord/lib/active_record/associations/collection_association.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ def merge_target_lists(persisted, memory)
338338

339339
def _create_record(attributes, raise = false, &block)
340340
unless owner.persisted?
341-
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
341+
raise ActiveRecord::RecordNotSaved.new("You cannot call create unless the parent is saved", owner)
342342
end
343343

344344
if attributes.is_a?(Array)

activerecord/lib/active_record/associations/has_one_association.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def replace(record, save = true)
7070
if save && !record.save
7171
nullify_owner_attributes(record)
7272
set_owner_attributes(target) if target
73-
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
73+
raise RecordNotSaved.new("Failed to save the new associated #{reflection.name}.", record)
7474
end
7575
end
7676
end
@@ -102,8 +102,11 @@ def remove_target!(method)
102102

103103
if target.persisted? && owner.persisted? && !target.save
104104
set_owner_attributes(target)
105-
raise RecordNotSaved, "Failed to remove the existing associated #{reflection.name}. " \
106-
"The record failed to save after its foreign key was set to nil."
105+
raise RecordNotSaved.new(
106+
"Failed to remove the existing associated #{reflection.name}. " \
107+
"The record failed to save after its foreign key was set to nil.",
108+
target
109+
)
107110
end
108111
end
109112
end
@@ -122,7 +125,7 @@ def transaction_if(value)
122125

123126
def _create_record(attributes, raise_error = false, &block)
124127
unless owner.persisted?
125-
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
128+
raise ActiveRecord::RecordNotSaved.new("You cannot call create unless the parent is saved", owner)
126129
end
127130

128131
super

activerecord/test/cases/associations/has_many_associations_test.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,21 +1034,23 @@ def test_adding_using_create
10341034
end
10351035

10361036
def test_create_with_bang_on_has_many_when_parent_is_new_raises
1037+
firm = Firm.new
10371038
error = assert_raise(ActiveRecord::RecordNotSaved) do
1038-
firm = Firm.new
10391039
firm.plain_clients.create! name: "Whoever"
10401040
end
10411041

10421042
assert_equal "You cannot call create unless the parent is saved", error.message
1043+
assert_equal firm, error.record
10431044
end
10441045

10451046
def test_regular_create_on_has_many_when_parent_is_new_raises
1047+
firm = Firm.new
10461048
error = assert_raise(ActiveRecord::RecordNotSaved) do
1047-
firm = Firm.new
10481049
firm.plain_clients.create name: "Whoever"
10491050
end
10501051

10511052
assert_equal "You cannot call create unless the parent is saved", error.message
1053+
assert_equal firm, error.record
10521054
end
10531055

10541056
def test_create_with_bang_on_has_many_raises_when_record_not_saved
@@ -1059,11 +1061,13 @@ def test_create_with_bang_on_has_many_raises_when_record_not_saved
10591061
end
10601062

10611063
def test_create_with_bang_on_habtm_when_parent_is_new_raises
1064+
developer = Developer.new("name" => "Aredridel")
10621065
error = assert_raise(ActiveRecord::RecordNotSaved) do
1063-
Developer.new("name" => "Aredridel").projects.create!
1066+
developer.projects.create!
10641067
end
10651068

10661069
assert_equal "You cannot call create unless the parent is saved", error.message
1070+
assert_equal developer, error.record
10671071
end
10681072

10691073
def test_adding_a_mismatch_class

activerecord/test/cases/associations/has_one_associations_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ def test_create_when_parent_is_new_raises
340340
end
341341

342342
assert_equal "You cannot call create unless the parent is saved", error.message
343+
assert_equal firm, error.record
343344
end
344345

345346
def test_reload_association
@@ -519,6 +520,7 @@ def test_creation_failure_due_to_new_record_should_raise_error
519520
end
520521

521522
assert_equal "Failed to save the new associated ship.", error.message
523+
assert_equal new_ship, error.record
522524
assert_nil pirate.ship
523525
assert_nil new_ship.pirate_id
524526
end
@@ -536,6 +538,7 @@ def test_replacement_failure_due_to_existing_record_should_raise_error
536538
assert_equal pirate.id, pirate.ship.pirate_id
537539
assert_equal "Failed to remove the existing associated ship. " \
538540
"The record failed to save after its foreign key was set to nil.", error.message
541+
assert_equal pirate.ship, error.record
539542
end
540543

541544
def test_replacement_failure_due_to_new_record_should_raise_error
@@ -547,6 +550,7 @@ def test_replacement_failure_due_to_new_record_should_raise_error
547550
end
548551

549552
assert_equal "Failed to save the new associated ship.", error.message
553+
assert_equal new_ship, error.record
550554
assert_equal ships(:black_pearl), pirate.ship
551555
assert_equal pirate.id, pirate.ship.pirate_id
552556
assert_equal pirate.id, ships(:black_pearl).reload.pirate_id

0 commit comments

Comments
 (0)