web-dev-qa-db-ja.com

Activestorageフィクスチャアタッチメント

Railsテスト。アクティブストレージのみの基本モデルがあります:

class User < ApplicationRecord
  has_one_attached :avatar
end

私はそれをフィクスチャにしようとしていますが、運がありません(私はそこに画像を持っています):

# users.yml
one:
  avatar: <%= File.open Rails.root.join('test', 'files', 'image.png').to_s %>

フィクスチャを介してアバターファイルを適切に添付するにはどうすればよいですか?

14
joseramonc

モデルユーザーのテストがあるとしましょう。デフォルトはUserTest#test_the_truthです。

Rails test test/models/user_test.rb

テスト中にエラーErrno::ENOENT: No such file or directory @ rb_sysopenが発生したと思います。パスにエラーがあるため、'fixtures'を追加する必要があります。次のようになります。

# users.yml
one:
  name: 'Jim Kirk'
  avatar: <%= File.open Rails.root.join('test', 'fixtures', 'files', 'image.png').to_s %>

しかし今、あなたはこのエラーを持っているはずです:ActiveRecord::Fixture::FixtureError: table "users" has no column named "avatar".

ActiveStorageはactive_storage_attachmentsactive_storage_blobsの2つのテーブルを使用して機能するため、これは正しいです。

したがって、users.ymlからアバター列を削除し、2つの新しいファイルを追加する必要があります。

# active_storage_attachments.yml
one:
  name: 'avatar'
  record_type: 'User'
  record_id: 1
  blob_id: 1

そして

# active_storage_blobs.yml
one:
  id: 1
  key: '12345678'
  filename: 'file.png'
  content_type: 'image/png'
  metadata: nil
  byte_size: 2000
  checksum: "123456789012345678901234"

また、App/modelsに、ActiveStorageが機能するために必要でない場合でもを追加します。

# active_storage_attachment.rb
class ActiveStorageAttachment < ApplicationRecord
end

そして

# active_storage_blob.rb
class ActiveStorageBlob < ApplicationRecord
end

その後、UserTest#test_the_truthは成功します。

しかし、より良い取り除くactive_storage_attachment.rbactive_storage_blob.rbそして別の方法でテストしてください。

アタッチメントが機能しているかどうかをテストするには、コントローラーをより適切にテストします、たとえば、このコードをtest/controllers/users_controller_test.rbに追加します。

require 'test_helper'

class UserControllerTest < ActionController::TestCase
  def setup
    @controller = UsersController.new
  end
  test "create user with avatar" do
    user_name = 'fake_name'
    avatar_image = fixture_file_upload(Rails.root.join('test', 'fixtures', 'files', 'avatar.png'),'image/png')
    post :create, params: {user: {name: user_name, avatar: avatar_image}}
  end
end

フォルダtmp/storageを確認してください。空になっているはずです。

次のコマンドでテストを開始します:Rails test test/controllers/users_controller_test.rb

成功するはずです。tmp/storageをもう一度チェックすると、テストによって生成されたいくつかのフォルダーとファイルが見つかります。

コメントの後に編集:Userモデルでコールバックをテストする必要がある場合、これは機能するはずです。

# Rails test test/models/user_test.rb

require 'test_helper'

class UserTest < ActiveSupport::TestCase
  test "should have avatar attached" do
    u = User.new
    u.name = 'Jim Kirk'
    file = Rails.root.join('test', 'fixtures', 'files', 'image.png')
    u.avatar.attach(io: File.open(file), filename: 'image.png') # attach the avatar, remove this if it is done with the callback
    assert u.valid?
    assert u.avatar.attached? # checks if the avatar is attached
  end
end

あなたのコールバックはわかりませんが、これがあなたにいくつかのヒントを与えることを願っています。

8
iGian

私が拡張したい唯一の答えについて、IS04による失われたコメントがあります。

私はしばらくの間これをしようとして立ち往生しました、そしてiGianの答えに従うことは私のために働きました。しかし、私のチームは私のPRをレビューし、ActiveStorage自身のモデル(つまり、ActiveStorage::AttachmentActiveStorage::Blob)に非常に近い名前の新しいモデルを導入する理由を尋ねました。

その後、フィクスチャをactive_storage_attachments.ymlからactive_storage/attachments.ymlに移動するだけでよいことに気付きました。

追加の調査で理解しなければならなかった他の部分は、自動生成されたIDでこれらのフィクスチャを使用する方法でした。このようにActiveRecord::FixtureSet.identifyを使用してこれを行いました:

attachment_identifier:
  name: "attachment_name"
  record_type: "MyRecordClass"
  record_id: <%= ActiveRecord::FixtureSet.identify(:my_record_identifier) %>
  blob_id: <%= ActiveRecord::FixtureSet.identify(:blob) %>
  created_at: <%= Time.zone.now %>
3
deadsalt

これは、誰もが考えているよりもはるかに簡単です。これらの答えに基づいてこれを理解するのに時間がかかったので、私は誰かを侮辱するつもりはありません。簡単にするために同じデータモデルを使用します。

ユーザーには「アバター」が1つ添付されています。このユーザーフィクスチャがあるとしましょう:

# users.yml
one:
  name: Fred

これがあなたがする必要があるすべてです:

% mkdir test/fixtures/active_storage

これで、「attachments.yml」と「blobs.yml」をそのディレクトリに配置するだけです。 「添付ファイル」レコードは、ユーザーだけでなくblobも参照します。

# active_storage/attachments.yml
freds_picture:
  name: avatar
  record: fred (User)
  blob: freds_picture_blob

そして

# active_storage/blobs.yml
freds_picture_blob:
  key: aabbWNGW1VrxZ8Eu4zmyw13A
  filename: fred.jpg
  content_type: image/jpeg
  metadata: '{"identified":true,"analyzed":true}'
  byte_size: 1000
  checksum: fdUivZUf74Y6pjAiemuvlg==

さて、それは添付の写真を持つために「機能」します。実際のファイルが必要な場合は、最初にconfig/storage.ymlを調べて、ファイルが保存されているパスを確認します。デフォルトでは、「tmp/storage」です。上記のファイルはここに保存されます:

tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zmyw13A

チェックサムを計算するには、次を参照してください。

Rails ActiveStorage のblobテーブルでチェックサムはどのように計算されますか

md5_checksum = Digest::MD5.file('tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zmyw13A').base64digest

フィクスチャでerbを使用して、ファイルサイズとチェックサムを入力することができます。

  byte_size: <%= File.size('tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zmyw13A') %>
  checksum: <%= Digest::MD5.file('tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zmyw13A').base64digest %>

最初にファイルをストレージディレクトリにコピーする必要があることに注意してください。

0
Michael Chaney