如何测试新文件是否与模型中的 Active Storage 一起发送?

ale*_*our 5 ruby-on-rails rails-activestorage

在我的 Rails 模型中,我有这个代码来强制上传时更改文件名:

before_save :set_filename  
  def set_filename
    if file.attached?
      self.file.blob.update(filename: "#{new_file_name()}.#{self.file.blob.content_type.split('/')[1]}")
    end
  end
Run Code Online (Sandbox Code Playgroud)

问题是即使没有在表单中发送新文件(编辑时),文件名也会更改。

我的附件只是命名文件:

# active storage
  has_one_attached :file
Run Code Online (Sandbox Code Playgroud)

上传时如何真正测试是否附加了新文件?

谢谢,

编辑:更多说明

我有一个带有 file_field 的表单。当我添加或修改表单的对象时,我想测试是否通过表单发送了新文件。

我的模型称为 Image,附加的文件称为 file。

class Image
  has_one_attached :file
end
Run Code Online (Sandbox Code Playgroud)

每次通过表单发送新文件时,我都想更改文件名,当然不是 file_field 保持为空。

kas*_*ite 5

你可以用new_record吗?检查是否file是新的,即:

  def set_filename
    if file.attached? && file.new_record?
      self.file.blob.update(filename: "#{new_file_name()}.#{self.file.blob.content_type.split('/')[1]}")
    end
  end
Run Code Online (Sandbox Code Playgroud)

或者,使用before_create代替,before_save以便set_name仅在上传新文件时运行。

更新

有趣的是,ActiveStorage 在模型钩子之外处理 blob 更改。显然,它现在甚至不支持验证。无法验证 blob 是否已更改,因为它的状态未在任何地方持久化。如果您查看 rails 日志,请注意只要添加了新的 blob,rails 就会清除旧的 blob。

我能想到的几个选项:

1.更新控制器中的文件名,例如:

original_name = params[:file].original_name
params[:file].original_name = # your logic goes here
Run Code Online (Sandbox Code Playgroud)

2.在父模型中存储blob文件名并在before_save.

  def set_filename
    if file.attached? && file.blob.filename != self.old_filename
      self.file.blob.update(filename: "#{new_file_name()}.#{self.file.blob.content_type.split('/')[1]}")
    end
  end
Run Code Online (Sandbox Code Playgroud)

这些解决方案都不是理想的,但希望它们能给你一些想法。