aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael França <rafaelmfranca@gmail.com>2019-06-24 13:59:15 -0400
committerGitHub <noreply@github.com>2019-06-24 13:59:15 -0400
commitb65f88652f835093030bf65b9e31e727ba58a6de (patch)
tree40e6e2afb2f230e31fd55b9828423265bb857682
parent58256db50750781016f5ea6d2dd6cbc72096062b (diff)
parentbbcd707aefe5da137137a8deb13908ec9a7db77d (diff)
downloadrails-b65f88652f835093030bf65b9e31e727ba58a6de.tar.gz
rails-b65f88652f835093030bf65b9e31e727ba58a6de.tar.bz2
rails-b65f88652f835093030bf65b9e31e727ba58a6de.zip
Merge pull request #36210 from vishaltelangre/raise-record-invalid-when-associations-fail-to-save-due-to-uniqueness-failure
Fix: ActiveRecord::RecordInvalid is not raised when an associated record fails to #save! due to uniqueness validation failure
-rw-r--r--activerecord/lib/active_record/autosave_association.rb2
-rw-r--r--activerecord/test/cases/autosave_association_test.rb41
-rw-r--r--activerecord/test/models/author.rb1
-rw-r--r--activerecord/test/models/book.rb6
4 files changed, 49 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb
index a7709b444d..94d8134b55 100644
--- a/activerecord/lib/active_record/autosave_association.rb
+++ b/activerecord/lib/active_record/autosave_association.rb
@@ -409,7 +409,7 @@ module ActiveRecord
saved = record.save(validate: false)
end
- raise ActiveRecord::Rollback unless saved
+ raise(RecordInvalid.new(association.owner)) unless saved
end
end
end
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 7e61ac9d8b..2d223a3035 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -2,6 +2,7 @@
require "cases/helper"
require "models/author"
+require "models/book"
require "models/bird"
require "models/post"
require "models/comment"
@@ -1671,6 +1672,10 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te
super
@pirate = Pirate.create(catchphrase: "Don' botharrr talkin' like one, savvy?")
@pirate.birds.create(name: "cookoo")
+
+ @author = Author.new(name: "DHH")
+ @author.published_books.build(name: "Rework", isbn: "1234")
+ @author.published_books.build(name: "Remote", isbn: "1234")
end
test "should automatically validate associations" do
@@ -1679,6 +1684,42 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te
assert_not_predicate @pirate, :valid?
end
+
+ test "rollbacks whole transaction and raises ActiveRecord::RecordInvalid when associations fail to #save! due to uniqueness validation failure" do
+ author_count_before_save = Author.count
+ book_count_before_save = Book.count
+
+ assert_no_difference "Author.count" do
+ assert_no_difference "Book.count" do
+ exception = assert_raises(ActiveRecord::RecordInvalid) do
+ @author.save!
+ end
+
+ assert_equal("Validation failed: Published books is invalid", exception.message)
+ end
+ end
+
+ assert_equal(author_count_before_save, Author.count)
+ assert_equal(book_count_before_save, Book.count)
+ end
+
+ test "rollbacks whole transaction when associations fail to #save due to uniqueness validation failure" do
+ author_count_before_save = Author.count
+ book_count_before_save = Book.count
+
+ assert_no_difference "Author.count" do
+ assert_no_difference "Book.count" do
+ assert_nothing_raised do
+ result = @author.save
+
+ assert_not(result)
+ end
+ end
+ end
+
+ assert_equal(author_count_before_save, Author.count)
+ assert_equal(book_count_before_save, Book.count)
+ end
end
class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::TestCase
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index b52b643ad7..da7e4139b1 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -116,6 +116,7 @@ class Author < ActiveRecord::Base
has_many :tags_with_primary_key, through: :posts
has_many :books
+ has_many :published_books, class_name: "PublishedBook"
has_many :unpublished_books, -> { where(status: [:proposed, :written]) }, class_name: "Book"
has_many :subscriptions, through: :books
has_many :subscribers, -> { order("subscribers.nick") }, through: :subscriptions
diff --git a/activerecord/test/models/book.rb b/activerecord/test/models/book.rb
index afdda1a81e..43b82e6047 100644
--- a/activerecord/test/models/book.rb
+++ b/activerecord/test/models/book.rb
@@ -24,3 +24,9 @@ class Book < ActiveRecord::Base
"do publish work..."
end
end
+
+class PublishedBook < ActiveRecord::Base
+ self.table_name = "books"
+
+ validates_uniqueness_of :isbn
+end