Skip to content

Commit

Permalink
Merge pull request #36210 from vishaltelangre/raise-record-invalid-wh…
Browse files Browse the repository at this point in the history
…en-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
  • Loading branch information
rafaelfranca committed Jun 24, 2019
2 parents 58256db + bbcd707 commit b65f886
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 1 deletion.
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/autosave_association.rb
Expand Up @@ -409,7 +409,7 @@ def save_collection_association(reflection)
saved = record.save(validate: false)
end

raise ActiveRecord::Rollback unless saved
raise(RecordInvalid.new(association.owner)) unless saved
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions activerecord/test/cases/autosave_association_test.rb
Expand Up @@ -2,6 +2,7 @@

require "cases/helper"
require "models/author"
require "models/book"
require "models/bird"
require "models/post"
require "models/comment"
Expand Down Expand Up @@ -1671,6 +1672,10 @@ def setup
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
Expand All @@ -1679,6 +1684,42 @@ def setup

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
Expand Down
1 change: 1 addition & 0 deletions activerecord/test/models/author.rb
Expand Up @@ -116,6 +116,7 @@ def ratings
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
Expand Down
6 changes: 6 additions & 0 deletions activerecord/test/models/book.rb
Expand Up @@ -24,3 +24,9 @@ def published!
"do publish work..."
end
end

class PublishedBook < ActiveRecord::Base
self.table_name = "books"

validates_uniqueness_of :isbn
end

0 comments on commit b65f886

Please sign in to comment.