The cause of the error
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
# create a new user record
user = User.create!
# create a new associated profile record (has_one)
original_profile = user.create_profile!
# attempt to replace the original profile with a new one
user.create_profile!
=> 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
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).
user.avatar.purge # or user.avatar.purge_later
user.avatar.attach(params[:file])
Is this desired behavior?
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: