错误的原因
has_one
此错误是由您的模型和附件记录之间的关联引发的。发生这种情况是因为尝试用新的附件替换原始附件会孤立原始附件并导致它无法通过belongs_to
关联的外键约束。这是所有 ActiveRecordhas_one
关系的行为(即它不是特定于 ActiveStorage)。
一个类似的例子
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.
在尝试创建新配置文件时,ActiveRecord 尝试将user_id
原始配置文件的 设置为nil
,这使记录的外键约束失败belongs_to
。我相信这本质上是当您尝试使用 ActiveStorage 将新文件附加到模型时发生的事情......这样做会尝试使原始附件记录的外键无效,这将失败。
解决方案
关系的解决方案has_one
是在尝试创建新记录之前销毁相关记录(即在尝试附加另一个记录之前清除附件)。
user.avatar.purge # or user.avatar.purge_later
user.avatar.attach(params[:file])
这是期望的行为吗?
在尝试为 has_one 关系附加新记录时,ActiveStorage 是否应该自动清除原始记录是一个不同的问题,最好向核心团队提出......
IMO 让它与所有其他 has_one 关系保持一致是有道理的,最好让开发人员在附加新记录之前明确清除原始记录而不是自动执行(这可能有点冒昧) )。
资源: