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

时间:2019-03-09 15:01:56

标签: 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

运行正常。它将一个图像附加到每个项目。

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

我尝试过:

# 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

但这会导致错误: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'
...

我觉得有一种方法可以为带有多个附件的行添加种子。

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

2 个答案:

答案 0 :(得分:1)

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

project.images.attach(io: image_file, filename: "placeholder_image.png", content_type: "image/png")

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

解决方案是通过调用#rewind将文件位置重新设置为开头:

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

您可以在image_file.rewind调用之前或之后project.images.attach,快退刚打开的文件并没有任何意义。您传递给#rewind的{​​{1}}并不总是支持io(或需要),因此Active Storage不能真正做到这一点。

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

#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 所缺少的do只是一个错字BTW。

答案 1 :(得分:0)

我通过简单地使用数组作为参数来实现它:

image_file = File.open("./db/seed_files/placeholder_image.png")
files = []
  rand(1..3).times do
    files << {io: image_file, 
              filename: "placeholder_image.png",
              content_type: "image/png"
             }
    project.images.attach(files)
  end