Activestorage 附件
Activestorage fixtures attachments
在rails 测试中。我有一个只有 activestorage 的基本模型:
class User < ApplicationRecord
has_one_attached :avatar
end
我正在努力让它成为固定装置,但运气不佳(我确实有一张图片):
# users.yml
one:
avatar: <%= File.open Rails.root.join('test', 'files', 'image.png').to_s %>
如何通过 fixtures 正确附加头像文件?
假设您对模型用户进行了测试,默认值 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_attachments
和 active_storage_blobs
。
因此,您需要从 users.yml
中删除头像栏并添加两个新文件:
(免责声明 另请参阅下面的评论:“无需创建自己的模型,因此您可以使用原始 ActiveStorage::Attachment
而不是 ActiveStorageAttachment
并将夹具放在下面active_storage 文件夹”,另请参阅 )
# 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.rb
和active_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
我不知道你的回调,但我希望这能给你一些提示。
IS04 对我只想扩展的唯一答案有一条丢失的评论。
一段时间以来,我在尝试执行此操作时遇到了困难,而遵循 iGian 的回答确实对我有用。然而,我的团队审查了我的 PR,并询问我为什么要引入与 ActiveStorage 自己的模型命名如此接近的新模型(即 ActiveStorage::Attachment
和 ActiveStorage::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 %>
这比任何人想象的要容易得多。我并不是要贬低任何人,因为我花了一些时间根据这些答案弄清楚了这一点。我将使用相同的数据模型来简化它。
用户附加了一个“头像”。假设您有这个用户装置:
# users.yml
fred:
name: Fred
您只需执行以下操作:
% mkdir test/fixtures/active_storage
现在,您只需将“attachments.yml”和“blobs.yml”放入该目录。 “附件”记录将引用 blob 以及用户(请注意 name
条目是 has_one_attached
字段的名称):
# 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==
service_name: local
key
在代码中是这样生成的:
ActiveStorage::Blob.generate_unique_secure_token
您可以 运行 在控制台中获取上述装置的密钥。
现在,附上图片将“起作用”。如果你需要实际的文件在那里,首先查看 config/storage.yml 以查看文件存储在什么路径中。默认情况下,它是“tmp/storage”。上面的文件将存储在这里:
tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zmyw13A
要计算校验和,请参见此处:
How is the checksum calculated in the blobs table for rails ActiveStorage
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 %>
请注意,您必须先将文件复制到存储目录中。
测试环境的存储根目录默认为tmp/storage/
,其余路径由key
(即tmp/storage/aa/bb
)的前四个字符构成。
感谢@Alex Ghiculescu 打开 Rails 的 PR,这让我了解到“Active Storage 的测试套件是如何做到的”。
不幸的是,该代码似乎不在 6.1 分支中,但它们有一个 ActiveStorage::FixtureSet
在此期间,您可以将此添加到您的 test_helper.rb
(或者您希望组织代码的方式:
class ActiveStorage::Blob
def self.fixture(filename:, **attributes)
blob = new(
filename: filename,
key: generate_unique_secure_token
)
io = Rails.root.join("test/fixtures/files/#{filename}").open
blob.unfurl(io)
blob.assign_attributes(attributes)
blob.upload_without_unfurling(io)
blob.attributes.transform_values { |values| values.is_a?(Hash) ? values.to_json : values }.compact.to_json
end
end
现在您可以像这样将 freds-picture.jpg
添加到 test/fixtures/files
和夹具文件中:
test/fixtures/active_storage/attachments.yml
freds_picture:
name: picture
record: fred (User)
blob: freds_picture_blob
和test/fixtures/active_storage/blobs.yml
freds_picture_blob: <%= ActiveStorage::Blob.fixture(
filename: "freds-picture.jpg"
) %>
希望这是有道理的,一旦 ActiveStorage::FixtureSet
出现在您的 Rails 版本中,您就可以删除 self.fixture
方法并将 ActiveStorage::Blob.fixture
替换为 ActiveStorage::FixtureSet.blob
fixture yaml 文件。
绝对适合我,在系统测试中加载渲染夹具的视图可以正确渲染图像。
现在(rails 7),根据 rails guides 看来正确的方法是:
# config/storage.yml
test_fixtures:
service: Disk
root: <%= Rails.root.join("tmp/storage_fixtures") %>
# active_storage/users.yml
david:
name: David
# active_storage/attachments.yml
david_avatar:
name: avatar
record: david (User)
blob: david_avatar_blob
# active_storage/blobs.yml
david_avatar_blob: <%= ActiveStorage::FixtureSet.blob filename: "david.png", service_name: "test_fixtures" %>
在rails 测试中。我有一个只有 activestorage 的基本模型:
class User < ApplicationRecord
has_one_attached :avatar
end
我正在努力让它成为固定装置,但运气不佳(我确实有一张图片):
# users.yml
one:
avatar: <%= File.open Rails.root.join('test', 'files', 'image.png').to_s %>
如何通过 fixtures 正确附加头像文件?
假设您对模型用户进行了测试,默认值 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_attachments
和 active_storage_blobs
。
因此,您需要从 users.yml
中删除头像栏并添加两个新文件:
(免责声明 另请参阅下面的评论:“无需创建自己的模型,因此您可以使用原始 ActiveStorage::Attachment
而不是 ActiveStorageAttachment
并将夹具放在下面active_storage 文件夹”,另请参阅
# 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.rb
和active_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
我不知道你的回调,但我希望这能给你一些提示。
IS04 对我只想扩展的唯一答案有一条丢失的评论。
一段时间以来,我在尝试执行此操作时遇到了困难,而遵循 iGian 的回答确实对我有用。然而,我的团队审查了我的 PR,并询问我为什么要引入与 ActiveStorage 自己的模型命名如此接近的新模型(即 ActiveStorage::Attachment
和 ActiveStorage::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 %>
这比任何人想象的要容易得多。我并不是要贬低任何人,因为我花了一些时间根据这些答案弄清楚了这一点。我将使用相同的数据模型来简化它。
用户附加了一个“头像”。假设您有这个用户装置:
# users.yml
fred:
name: Fred
您只需执行以下操作:
% mkdir test/fixtures/active_storage
现在,您只需将“attachments.yml”和“blobs.yml”放入该目录。 “附件”记录将引用 blob 以及用户(请注意 name
条目是 has_one_attached
字段的名称):
# 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==
service_name: local
key
在代码中是这样生成的:
ActiveStorage::Blob.generate_unique_secure_token
您可以 运行 在控制台中获取上述装置的密钥。
现在,附上图片将“起作用”。如果你需要实际的文件在那里,首先查看 config/storage.yml 以查看文件存储在什么路径中。默认情况下,它是“tmp/storage”。上面的文件将存储在这里:
tmp/storage/aa/bb/aabbWNGW1VrxZ8Eu4zmyw13A
要计算校验和,请参见此处:
How is the checksum calculated in the blobs table for rails ActiveStorage
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 %>
请注意,您必须先将文件复制到存储目录中。
测试环境的存储根目录默认为tmp/storage/
,其余路径由key
(即tmp/storage/aa/bb
)的前四个字符构成。
感谢@Alex Ghiculescu 打开 Rails 的 PR,这让我了解到“Active Storage 的测试套件是如何做到的”。 不幸的是,该代码似乎不在 6.1 分支中,但它们有一个 ActiveStorage::FixtureSet
在此期间,您可以将此添加到您的 test_helper.rb
(或者您希望组织代码的方式:
class ActiveStorage::Blob
def self.fixture(filename:, **attributes)
blob = new(
filename: filename,
key: generate_unique_secure_token
)
io = Rails.root.join("test/fixtures/files/#{filename}").open
blob.unfurl(io)
blob.assign_attributes(attributes)
blob.upload_without_unfurling(io)
blob.attributes.transform_values { |values| values.is_a?(Hash) ? values.to_json : values }.compact.to_json
end
end
现在您可以像这样将 freds-picture.jpg
添加到 test/fixtures/files
和夹具文件中:
test/fixtures/active_storage/attachments.yml
freds_picture:
name: picture
record: fred (User)
blob: freds_picture_blob
和test/fixtures/active_storage/blobs.yml
freds_picture_blob: <%= ActiveStorage::Blob.fixture(
filename: "freds-picture.jpg"
) %>
希望这是有道理的,一旦 ActiveStorage::FixtureSet
出现在您的 Rails 版本中,您就可以删除 self.fixture
方法并将 ActiveStorage::Blob.fixture
替换为 ActiveStorage::FixtureSet.blob
fixture yaml 文件。
绝对适合我,在系统测试中加载渲染夹具的视图可以正确渲染图像。
现在(rails 7),根据 rails guides 看来正确的方法是:
# config/storage.yml
test_fixtures:
service: Disk
root: <%= Rails.root.join("tmp/storage_fixtures") %>
# active_storage/users.yml
david:
name: David
# active_storage/attachments.yml
david_avatar:
name: avatar
record: david (User)
blob: david_avatar_blob
# active_storage/blobs.yml
david_avatar_blob: <%= ActiveStorage::FixtureSet.blob filename: "david.png", service_name: "test_fixtures" %>