当尝试使用附件为数据库播种时,为什么会收到“ActiveStorage::FileNotFoundError”?

use*_*603 6 ruby-on-rails rails-activestorage

我正在尝试为我的开发数据库播种。其中一个模型Project有与之相关的图像。

我已经在 中放置了占位符图像./db/seed_files/。我的种子文件如下所示:

# Add projects
1000.times do
  project = Project.new(
    name: Faker::Marketing.buzzwords.capitalize,
    description: Faker::Lorem.sentence(rand(1..30))
  )
  image_file = File.open("./db/seed_files/placeholder_image.png")
  project.images.attach(io: image_file, filename: "placeholder_image.png", content_type: "image/png")
  project.save
end
Run Code Online (Sandbox Code Playgroud)

这运行良好。它为每个项目附加一张图像。

但是,我想为每个项目添加多个图像。我想我可以多次附加同一张图片。

我努力了:

# Add projects
1000.times do
  project = Project.new(
    name: Faker::Marketing.buzzwords.capitalize,
    description: Faker::Lorem.sentence(rand(1..30))
  )
  image_file = File.open("./db/seed_files/placeholder_image.png")
  rand(1..3).times do
    project.images.attach(io: image_file, filename: "placeholder_image.png", content_type: "image/png")
  end
  project.save
end
Run Code Online (Sandbox Code Playgroud)

但这会导致错误:ActiveStorage::FileNotFoundError

/Users/greidods/.rvm/gems/ruby-2.6.1/bundler/gems/rails-b366be3b5b28/activestorage/lib/active_storage/service/disk_service.rb:136:in `rescue in stream'
/Users/greidods/.rvm/gems/ruby-2.6.1/bundler/gems/rails-b366be3b5b28/activestorage/lib/active_storage/service/disk_service.rb:129:in `stream'
/Users/greidods/.rvm/gems/ruby-2.6.1/bundler/gems/rails-b366be3b5b28/activestorage/lib/active_storage/service/disk_service.rb:28:in `block in download'
/Users/greidods/.rvm/gems/ruby-2.6.1/bundler/gems/rails-b366be3b5b28/activesupport/lib/active_support/notifications.rb:180:in `block in instrument'
/Users/greidods/.rvm/gems/ruby-2.6.1/bundler/gems/rails-b366be3b5b28/activesupport/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
...
Run Code Online (Sandbox Code Playgroud)

我有一种感觉,有一种方法可以用多个附件播种一行。

是什么导致了这个错误?为什么我可以附加图像一次但不能附加多次?

mu *_*ort 3

我无法完全重现您的问题(我不断收到ActiveStorage::IntegrityError异常而不是ActiveStorage::FileNotFoundError),但我想我知道发生了什么。第一次附加图像后:

project.images.attach(io: image_file, filename: "placeholder_image.png", content_type: "image/png")
Run Code Online (Sandbox Code Playgroud)

image_file当前位置将位于文件末尾。现在,当 Active Storage 尝试再次读取该文件时,它不会获取任何数据,因此校验和失败(我的IntegrityError)或 Active Storage 认为那里没有文件(您的FileNotFoundError)。

解决方案是通过调用以下命令将文件位置重置回开头#rewind

rand(1..3).times do
  project.images.attach(io: image_file, filename: "placeholder_image.png", content_type: "image/png")
  image_file.rewind
end
Run Code Online (Sandbox Code Playgroud)

您可以在调用image_file.rewind之前或之后project.images.attach,倒带新打开的文件不会做任何有趣的事情。您传递给#rewind的对象并不总是支持(或需要),因此 Active Storage 本身无法真正做到这一点。io#attach

或者,您可以在每次迭代时打开该文件:

rand(1..3).times do
  image_file = File.open("./db/seed_files/placeholder_image.png")
  project.images.attach(io: image_file, filename: "placeholder_image.png", content_type: "image/png")
end
Run Code Online (Sandbox Code Playgroud)

我假设您问题中缺少dotimes块只是一个拼写错误。