Ruby on Rails
Tuesday, August 29, 2017
This error is being raised by the has_one association between your model and the attachment record. It occurs because trying to replace the original attachment with a new one will orphan the original and cause it to fail the foreign key constraint for belongs_to associations. This is the behavior for all ActiveRecord has_one relationships (i.e. it's not specific to ActiveStorage).
An analogous example:
class User < ActiveRecord::Base
has_one :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
user = User.create!
original_profile = user.create_profile!
user.create_profile! # attempt to replace the original profile with a new one
=> ActiveRecord::RecordNotSaved: Failed to remove the existing associated profile. The record failed to save after its foreign key was set to nil.
In attempting to create a new profile, ActiveRecord tries to set the user_id of the original profile to nil, which fails the foreign key constraint for belongs_to records. I believe this is essentially what is happening when you try and attach a new file to your model using ActiveStorage… doing so tries to nullify the foreign key of the original attachment record, which will fail.
The solution for has_one relationships is to destroy the associated record before trying to create a new one (i.e. purging the attachment before trying to attach another one).
Whether or not ActiveStorage should automatically purge the original record when trying to attach a new one for has_one relationships is a different question best posed to the core team…
IMO having it work consistently with all other has_one relationships makes sense, and it may be preferable to leave it up to the developer to be explicit about purging an original record before attaching a new one rather than doing it automatically (which may be a bit presumptuous).
Resources:
On Friday, August 25, 2017 at 4:51:17 AM UTC-7, Henning wrote:We currently switched to Rails 5.2 to get the awesome functionalities of ActiveStorage.Up until now I was able to upload, delete (purge), and show files as expected - but I am not quite sure on how to update an attachment the right way.Here are the steps to reproduce:user.avatar.attached?=> falseuser.avatar.attach(io: File.open("~/avatar.png"), content_type: "image/png", filename: "avatar")=> #<ActiveStorage::Attachment id: 2, name: "avatar", record_type: "User", ...user.avatar.attached?=> trueuser.avatar.attach(io: File.open("~/avatar2.png"), content_type: "image/png", filename: "avatar2")=> Exception: ActiveRecord::RecordNotSaved: Failed to remove the existing associated avatar_attachment. The record failed to save after its foreign key was set to nil.user.avatar.purge=> niluser.avatar.attached?=> falseuser.avatar.attach(io: File.open("~/avatar2.png"), content_type: "image/png", filename: "avatar2")=> #<ActiveStorage::Attachment id: 2, name: "avatar2", record_type: "User", ...I don't think it should be necessary to purge the first attachment to attach a new one. So how can this be achieved properly?
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/8e9ab75b-57a8-4452-a61d-532c93571e7f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment