如何解决fixture_file_upload & Rack::Test::UploadedFile - ActiveStorage::IntegrityError
这是一个有趣的 ActiveStorage 问题,它让我困惑了几天; ActiveStorage 似乎无法与 fixture_file_upload
和 Rack::Test::UploadedFile
搭配使用,因为这两种方法在使用 ActiveStorage 将文件保存到模型附件时都会引发以下错误:
Loading development environment (Rails 6.0.3.4)
irb(main):001:0> Attachment.create({file: Rack::Test::UploadedFile.new("#{Rails.root}/test/fixtures/files/tracer1.jpg",'tracer1.jpg')})
D,[2021-01-22T16:20:03.695894 #498] DEBUG -- : (0.3ms) BEGIN
D,[2021-01-22T16:20:03.730325 #498] DEBUG -- : Attachment Create (0.8ms) INSERT INTO "attachments" ("created_at","updated_at") VALUES ($1,$2) RETURNING "id" [["created_at","2021-01-22 16:20:03.726078"],["updated_at","2021-01-22 16:20:03.726078"]]
D,[2021-01-22T16:20:03.735233 #498] DEBUG -- : ActiveStorage::Attachment Load (0.4ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id",1],["record_type","Attachment"],["name","file"],["LIMIT",1]]
D,[2021-01-22T16:20:03.736695 #498] DEBUG -- : ActiveStorage::Blob Create (0.3ms) INSERT INTO "active_storage_blobs" ("key","filename","content_type","metadata","byte_size","checksum","created_at") VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING "id" [["key","uk44hg6aeqgkijnoti7625kmymn5"],["filename","tracer1.jpg"],["content_type","image/jpeg"],["metadata","{\"identified\":true}"],["byte_size",71843],["checksum","fleS+FPvNcLEHaUysUgaGQ=="],["created_at","2021-01-22 16:20:03.735850"]]
D,[2021-01-22T16:20:03.737593 #498] DEBUG -- : ActiveStorage::Attachment Create (0.4ms) INSERT INTO "active_storage_attachments" ("name","record_type","record_id","blob_id",$5) RETURNING "id" [["name",["record_id",["blob_id",4],"2021-01-22 16:20:03.736870"]]
D,[2021-01-22T16:20:03.739022 #498] DEBUG -- : Attachment Update (0.3ms) UPDATE "attachments" SET "updated_at" = $1 WHERE "attachments"."id" = $2 [["updated_at","2021-01-22 16:20:03.737884"],["id",[2021-01-22T16:20:03.740233 #498] DEBUG -- : (1.1ms) COMMIT
I,[2021-01-22T16:20:03.740753 #498] INFO -- : Disk Storage (0.0ms) Deleted file from key: uk44hg6aeqgkijnoti7625kmymn5
I,[2021-01-22T16:20:03.740868 #498] INFO -- : Disk Storage (0.5ms) Uploaded file to key: uk44hg6aeqgkijnoti7625kmymn5 (checksum: fleS+FPvNcLEHaUysUgaGQ==)
Traceback (most recent call last):
1: from (irb):1
ActiveStorage::IntegrityError (ActiveStorage::IntegrityError)
但是,使用以下附加文件的方法时不会出现此问题。
irb(main):001:0> attachment = Attachment.new
=> #<Attachment id: nil,created_at: nil,updated_at: nil,parent_type: nil,parent_id: nil,frame: "{}",user_id: nil>
irb(main):002:0> attachment.file.attach(io: File.open(Rails.root + 'test/fixtures/files/tracer1.jpg'),filename: 'tracer1.jpg',content_type: 'image/jpg')
=> #<ActiveStorage::Attached::Changes::CreateOne:0x0000563b16d6bdc8 @name="file",@record=#<Attachment id: nil,user_id: nil>,@attachable={:io=>#<File:/app/test/fixtures/files/tracer1.jpg>,:filename=>"tracer1.jpg",:content_type=>"image/jpg"}>
irb(main):003:0> attachment.save
D,[2021-01-22T16:21:55.564371 #516] DEBUG -- : (0.2ms) BEGIN
D,[2021-01-22T16:21:55.610210 #516] DEBUG -- : Attachment Create (0.5ms) INSERT INTO "attachments" ("created_at","2021-01-22 16:21:55.605710"],"2021-01-22 16:21:55.605710"]]
D,[2021-01-22T16:21:55.615088 #516] DEBUG -- : ActiveStorage::Attachment Load (0.4ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id",2],[2021-01-22T16:21:55.617341 #516] DEBUG -- : ActiveStorage::Blob Create (0.6ms) INSERT INTO "active_storage_blobs" ("key","hjmhqkujbe2uxk6f9jfgmq5j4nn7"],"2021-01-22 16:21:55.615787"]]
D,[2021-01-22T16:21:55.618972 #516] DEBUG -- : ActiveStorage::Attachment Create (0.7ms) INSERT INTO "active_storage_attachments" ("name",5],"2021-01-22 16:21:55.617781"]]
D,[2021-01-22T16:21:55.621752 #516] DEBUG -- : Attachment Update (0.5ms) UPDATE "attachments" SET "updated_at" = $1 WHERE "attachments"."id" = $2 [["updated_at","2021-01-22 16:21:55.619356"],2]]
D,[2021-01-22T16:21:55.627906 #516] DEBUG -- : (6.0ms) COMMIT
I,[2021-01-22T16:21:55.628651 #516] INFO -- : Disk Storage (0.4ms) Uploaded file to key: hjmhqkujbe2uxk6f9jfgmq5j4nn7 (checksum: fleS+FPvNcLEHaUysUgaGQ==)
I,[2021-01-22T16:21:55.632122 #516] INFO -- : Enqueued ActiveStorage::AnalyzeJob (Job ID: 5e869e72-e190-4a73-8938-14db177822a0) to Async(active_storage_analysis) with arguments: #<GlobalID:0x0000563b18c40938 @uri=#<URI::GID gid://cosplay/ActiveStorage::Blob/5>>
=> true
irb(main):004:0> D,[2021-01-22T16:21:55.691199 #516] DEBUG -- : ActiveStorage::Blob Load (0.3ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2 [["id",1]]
I,[2021-01-22T16:21:55.691873 #516] INFO -- : Performing ActiveStorage::AnalyzeJob (Job ID: 5e869e72-e190-4a73-8938-14db177822a0) from Async(active_storage_analysis) enqueued at 2021-01-22T16:21:55Z with arguments: #<GlobalID:0x0000563b1947abf8 @uri=#<URI::GID gid://cosplay/ActiveStorage::Blob/5>>
I,[2021-01-22T16:21:55.797208 #516] INFO -- : Disk Storage (0.1ms) Downloaded file from key: hjmhqkujbe2uxk6f9jfgmq5j4nn7
D,[2021-01-22T16:21:55.845133 #516] DEBUG -- : (0.4ms) BEGIN
D,[2021-01-22T16:21:55.845853 #516] DEBUG -- : ActiveStorage::Blob Update (0.5ms) UPDATE "active_storage_blobs" SET "metadata" = $1 WHERE "active_storage_blobs"."id" = $2 [["metadata","{\"identified\":true,\"width\":575,\"height\":862,\"analyzed\":true}"],5]]
D,[2021-01-22T16:21:55.847209 #516] DEBUG -- : (0.9ms) COMMIT
I,[2021-01-22T16:21:55.847513 #516] INFO -- : Performed ActiveStorage::AnalyzeJob (Job ID: 5e869e72-e190-4a73-8938-14db177822a0) from Async(active_storage_analysis) in 155.55ms
这是上面两个示例中使用的模型。
class Attachment < ApplicationRecord
has_one_attached :file,dependent: :destroy
end
我真的很感谢任何人在这个问题上的帮助或见解;我基本上有一个非常大的测试套件,它几乎在任何地方都使用 fixture_file_upload
和 Rack::Test::UploadedFile
,因为它们非常有用,但是,正如您所看到的,它们不再与 ActiveStorage 结合使用。
这是我的 Gemfile & Gemfile.lock,如果它有助于调试正在发生的事情;我还在那个要点上包含了一个 minitest 测试文件,其中有 2 个失败和 1 个成功的测试。如果有助于调试问题,我很乐意提供任何其他详细信息。
可能有帮助的其他详细信息:
Docker 版本 20.10.2,构建 2291f61
docker-compose 版本 1.25.5,构建未知
解决方法
就我而言,像这样的参数是有效的:
Attachment.create(file: Rack::Test::UploadedFile.new(Rails.root.join('test','fixtures','files','test.jpg'),'image/jpg'))
对于测试,你可以试试这个:
# Step 1,test_helper.rb
FactoryBot::SyntaxRunner.class_eval do
# If you want to use `fixture_file_upload` with Rails 6.0
include ActionDispatch::TestProcess
# You may need this to use `fixture_file_upload` with Rails 6.1
include ActiveSupport::Testing::FileFixtures
end
# Step 2,attachments.rb
factory :attachment do
name { 'name' }
# As a must have attribute
file {
fixture_file_upload(
Rails.root.join('test','image/jpg')
}
# As an optional attribute
trait :with_file do
file {
fixture_file_upload(
Rails.root.join('test','image/jpg')
}
end
end
# You could replace `fixture_file_upload` with `Rack::Test::UploadedFile.new`
# Step 3,now you can use:
# As a must have attribute
attachment1 = create(:attachment)
attributes1 = attributes_for(:attachment)
# As an optional attribute
attachment2 = create(:attachment,:with_file)
attributes2 = attributes_for(:attachment,:with_file)
,
我有同样的问题,我知道这不是最好的解决方案,但它可能对您有用:
FactoryBot.define do
factory :user do
full_name { FFaker::NameBR.name }
email { FFaker::Internet.unique.email }
trait :with_avatar_image do
after(:build) do |user|
user.avatar_image.attach(io: File.open('public/examples/my_image.jpg'),filename: 'my_image.jpg')
end
end
end
end
所以这样创建:
let!(:user) { create(:user,:with_avatar_image) }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。