在factorybot中附加ActiveStorage文件

23

我正在寻找一种创建拥有Active Storage附件模型的工厂的方法。

我尝试了这篇文章中的方法,

并在我的工厂中使用了它。

factory :activity_fit_file, class: 'Activity' do
    association :user, factory: :user
    activity_type {:cycling}
    original_activity_log_file { fixture_file_upload("#{Rails.root}/spec/files/example_fit_file.fit") }
end

但我收到了这个错误

 NoMethodError:
   undefined method `fixture_file_upload' for #<FactoryBot::SyntaxRunner:0x000000000208c5f8>

如何在 ActiveStorage 中正确附加文件?

3个回答

46

直接使用 Rack::Test::UploadedFile 尝试:

file { Rack::Test::UploadedFile.new('path', 'image/png') }

1
undefined method upload' for nil:NilClass# /home/user/.rvm/gems/ruby-2.5.1/gems/activestorage-5.2.0/app/models/active_storage/blob.rb:155:in upload' - Qwertie
1
可能是文件路径有问题,请尝试使用 spec/files/example_fit_file.fit - s3tjan
2
好的,这就是解决方案,但我忘记在测试环境中设置config.active_storage.service。 - Qwertie
3
这在过去的几年中一直对我有效,但升级到Rails 6.1.3后,出现了“ActiveStorage :: IntegrityError”错误。关于该错误没有太多信息。 - Archonic
1
@joe 实际上并不是 Rails 升级的问题,而是 Docker for Mac 的 bug。我在这里写了一篇相关文章:https://github.com/rails/rails/issues/41991 - Archonic
显示剩余2条评论

35

这个解决方案适用于Rails 6:

factory :post do
  # ...
  after(:build) do |post|
    post.image.attach(
      io: File.open(Rails.root.join('test', 'fixture_files', 'test.jpg')),
      filename: 'test.jpg',
      content_type: 'image/jpeg'
    )
  end
end

6
这应该是适用于Rails 6+的被接受的解决方案。请注意,您还可以使用FactoryBot的瞬态属性来将附件相关信息与模型一起传递,例如after(:build) { |item, ev| item.image.attach(io: File.open(ev.image_path, 'rb'), filename: File.basename(ev.image_path), content_type: MiniMime.lookup_by_filename(ev.image_path)) if ev.image_path } - David Moles
1
我可以确认这个有效。在数月没有错误后,我突然使用Rack::Test::UploadedFile方法时出现了ActiveStorage::IntegrityError错误,因此我转而使用了这种方法。 - joe

1
将您的代码更改为以下内容,它将可以工作。
include ActionDispatch::TestProcess
factory :activity_fit_file, class: 'Activity' do
    association :user, factory: :user
    activity_type {:cycling}
    original_activity_log_file { fixture_file_upload("#{Rails.root}/spec/files/example_fit_file.fit") }
end

不建议包含 ActionDispatch::TestProcess,因为它包含其他方法,例如 #session,这会覆盖所有对象上现有的方法。请参见:https://github.com/honeybadger-io/honeybadger-ruby/blob/a18b1c3c4d912f96f1a3cb1435cc8a50e436f7f5/lib/honeybadger/notice.rb#L487 和 https://dev59.com/KWMl5IYBdhLWcg3wsIuA#23220853。 - s3tjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接