Почему я получаю `ActiveStorage :: FileNotFoundError` при попытке заполнить базу данных вложениями? - PullRequest
1 голос
/ 09 марта 2019

Я пытаюсь заполнить свою базу данных разработки.С одной из моделей 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'
...

У меня такое ощущение, что есть подход к заполнению строки несколькими вложениями.

Что вызывает эту ошибку?Почему я могу прикрепить изображение один раз, но не несколько раз?

1 Ответ

1 голос
/ 09 марта 2019

Я не могу точно воспроизвести вашу проблему (я получаю 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).

Решение состоит в том, чтобы сбросить позицию файла обратно в начало, вызвав #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 не всегда будет поддерживаться (или желаться) io, который вы передаете #attach, поэтому Active Storage не может сделать это сам.

Кроме того, вы можете открыть файл на каждой итерации:

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 для блока times в вашем вопросе - просто опечатка.

...