【问题标题】:fixture_file_upload & Rack::Test::UploadedFile - ActiveStorage::IntegrityErrorfixture_file_upload & Rack::Test::UploadedFile - ActiveStorage::IntegrityError
【发布时间】:2021-01-22 16:41:54
【问题描述】:

这是一个有趣的 ActiveStorage 问题,这几天让我摸不着头脑; ActiveStorage 似乎不能很好地与fixture_file_uploadRack::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", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["name", "file"], ["record_type", "Attachment"], ["record_id", 1], ["blob_id", 4], ["created_at", "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", 1]]
D, [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, created_at: nil, updated_at: nil, parent_type: nil, parent_id: nil, frame: "{}", 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", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", "2021-01-22 16:21:55.605710"], ["updated_at", "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], ["record_type", "Attachment"], ["name", "file"], ["LIMIT", 1]]
D, [2021-01-22T16:21:55.617341 #516] DEBUG -- :   ActiveStorage::Blob Create (0.6ms)  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", "hjmhqkujbe2uxk6f9jfgmq5j4nn7"], ["filename", "tracer1.jpg"], ["content_type", "image/jpeg"], ["metadata", "{\"identified\":true}"], ["byte_size", 71843], ["checksum", "fleS+FPvNcLEHaUysUgaGQ=="], ["created_at", "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", "record_type", "record_id", "blob_id", "created_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["name", "file"], ["record_type", "Attachment"], ["record_id", 2], ["blob_id", 5], ["created_at", "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"], ["id", 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", 5], ["LIMIT", 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}"], ["id", 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

这是上述 2 个示例中使用的模型。

class Attachment < ApplicationRecord
  has_one_attached :file, dependent: :destroy
end

我非常感谢任何人在此问题上提供的任何帮助或见解;我基本上有一个非常大的测试套件,它几乎在任何地方都使用Rack::Test::UploadedFile,因为它们非常有用,但是,正如您所见,它们不再与 ActiveStorage 结合使用。

这是我的Gemfile & Gemfile.lock,如果它有助于调试正在发生的事情;我还在那个要点上包含了一个 minitest 测试文件,其中有 2 个失败和 1 个成功的测试。如果有助于调试问题,我很乐意提供任何其他详细信息。

可能有帮助的其他详细信息:

Docker 版本 20.10.2,内部版本 2291f61

docker-compose 版本 1.25.5,构建未知

【问题讨论】:

    标签: ruby-on-rails activerecord ruby-on-rails-6 minitest rails-activestorage


    【解决方案1】:

    我有同样的问题,我知道这不是最好的解决方案,但它可能对你有用:

    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) }
    

    【讨论】:

    • 感谢您的回答;这也是我在短期内为克服某些测试用例中的问题所做的。不幸的是,这基本上只是避免了这个问题。此外,我相信 attributes_for 方法不会在我的测试中包含此配置中生成的对象中的附件,这意味着在功能测试设置中使用工厂会有点麻烦。我仍然没有从我的最终找到任何其他解决方案,但如果我想出一些东西,肯定会在这个线程上更新。
    【解决方案2】:

    就我而言,使用这样的参数可以:

    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', 'fixtures', 'files', 'test.jpg'), 'image/jpg')
      }
    
      # As an optional attribute
      trait :with_file do
        file {
          fixture_file_upload(
            Rails.root.join('test', 'fixtures', 'files', 'test.jpg'), '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)
    

    【讨论】:

      猜你喜欢
      • 2019-04-15
      • 2019-02-19
      • 2021-05-02
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-17
      • 2017-09-02
      • 2011-12-03
      相关资源
      最近更新 更多