ActiveStorage绑定JS文件时陷入递归创建删除循环问题求助
解决ActiveStorage附件创建删除循环问题
核心原因排查:回调触发无限循环
最常见的问题根源是Property模型中存在after_save、before_save这类保存回调,在执行js_file.attach时触发模型保存,进而再次触发回调,形成创建→删除→创建的无限循环。
验证步骤
- 临时注释Property模型中所有与保存相关的回调
- 在控制台重新执行attach操作,观察日志是否还出现循环
- 若循环停止,逐个恢复回调,定位到触发循环的具体回调
针对性解决方案
方案1:给回调添加触发条件
如果必须在回调中执行attach,通过条件判断避免重复触发:
# Property模型中的回调方法 def generate_and_attach_js_file # 仅当JS文件未附加,或确实需要更新时执行 return if js_file.attached? && !js_needs_update? dir = Rails.root.join("tmp/files") File.open("#{dir}/#{id}.js", "w") { |f| f.write "function(){};" } js_file.attach( io: File.open("#{dir}/#{id}.js"), filename: "#{id}.js", content_type: 'application/javascript' ) end # 根据业务逻辑定义是否需要更新的判断方法 def js_needs_update? # 示例:判断关联属性是否变更,或文件内容需要更新 true/false end
方案2:手动操作Blob和Attachment(绕开模型回调)
直接调用ActiveStorage底层API,避免触发模型的保存回调:
dir = Rails.root.join("tmp/files") File.open("#{dir}/#{self.id}.js", "w") { |f| f.write "function(){};" } # 先上传文件生成Blob blob = ActiveStorage::Blob.create_and_upload!( io: File.open("#{dir}/#{self.id}.js"), filename: "#{self.id}.js", content_type: 'application/javascript' ) # 手动创建Attachment与模型的关联 ActiveStorage::Attachment.create!( name: :js_file, record: self, blob: blob )
方案3:临时跳过回调执行保存
如果必须使用模型的attach方法,临时禁用触发循环的回调:
dir = Rails.root.join("tmp/files") File.open("#{dir}/#{self.id}.js", "w") { |f| f.write "function(){};" } # 临时跳过触发循环的回调(替换为你的回调方法名) self.class.skip_callback(:save, :after, :generate_and_attach_js_file) self.js_file.attach( io: File.open("#{dir}/#{self.id}.js"), filename: "#{self.id}.js", content_type: 'application/javascript' ) # 恢复回调 self.class.set_callback(:save, :after, :generate_and_attach_js_file)
其他排查方向
- 检查是否使用了第三方gem或自定义ActiveStorage扩展,这类代码可能干扰附件的创建流程
- 确认Rails版本是否存在ActiveStorage已知bug,尝试升级到稳定版本(如Rails 7.0+)
内容的提问来源于stack exchange,提问作者dchun
相关产品推荐
相关产品推荐

