has_one association may silently drop associated record when it is invalid

Updated . Posted . Visible to the public.

This is quite an edge case, and appears like a bug in Rails (4.2.6) to me.

Update: This is now documented on Edgeguides Ruby on Rails Show archive.org snapshot :

If you set the :validate option to true, then associated objects will be validated whenever you save this object. By default, this is false: associated objects will not be validated when this object is saved.

Setup

# post.rb
class Post < ActiveRecord::Base
  has_one :attachment
end
# attachment.rb
class Attachment < ActiveRecord::Base
  belongs_to :post
  validates :title, presence: true
end

Issue

When creating a post with an invalid attachment, I expect the creation to fail because of attachment validation errors. However, the attachment is silently not stored to the database.

post = Post.create!(attachment: Attachment.new)
post.id # => 123
post.attachment.id # => nil

This only happens …

  • when relying on autosave. Explicitly setting autosave: true fixes this. Also, adding validate: true to has_one :attachment fixes this.
  • with has_one. When it's has_many :attachments, validation errors of the attachment properly cancel the creation of the post.
  • when creating both post and attachment at the same time. Updating an already persisted post with an invalid attachment cancels the update.
Dominik Schöler
Last edit
Emanuel
License
Source code in this card is licensed under the MIT License.
Posted by Dominik Schöler to makandra dev (2016-07-13 07:17)