Activestorage固定装置附件

时间:2018-05-21 17:09:35

标签: ruby-on-rails rails-activestorage

在轨道测试中。我有一个只有activestorage的基本模型:

class User < ApplicationRecord
  has_one_attached :avatar
end

我正试图让它成为固定装置,但没有运气(我确实有一个图像):

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

如何通过灯具正确附加头像文件?

5 个答案:

答案 0 :(得分:6)

假设您对模型用户进行了测试,默认为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

因此,您需要从users.yml中移除头像列并添加两个新文件:

# 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

我不知道你的回调,但我希望这会给你一些提示。

答案 1 :(得分:6)

感谢@Alex Ghiculescu 向 Rails 开放 PR,它向我指出“Active Storage 的测试套件是如何做到的”。 不幸的是,该代码似乎不在 6.1 分支中,但它们有一个 ActiveStorage::FixtureSet

同时,您可以将其添加到您的 Col = colorRampPalette(brewer.pal(8, "Oranges"))(5) idx = which(!is.na(a),arr.ind=TRUE) z = c(a) zlim = range(z) nc = length(Col) z = (z - zlim[1L])/diff(zlim) zi = floor((nc - 1e-5) * z + 1e-7) plot(idx[,2],idx[,1],col=Col[zi+1],pch=15,cex=4,xaxt="n",yaxt="n") axis(1,at=1:nc,colnames(a)) axis(2,at=1:nc,rownames(a)) (或者您想组织代码的任何方式:

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" ) %> 在您的 Rails 版本中,您可以删除 ActiveStorage::FixtureSet 方法并将 self.fixture 替换为您的夹具 yaml 文件中的 ActiveStorage::Blob.fixture

绝对对我有用,加载一个在系统测试中渲染夹具的视图会正确渲染图像。

答案 2 :(得分:3)

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 :(得分:1)

现在,根据 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" %>

答案 4 :(得分:0)

这远比任何人都容易做到的容易。我并不是要贬低任何人,因为我花了一些时间根据这些答案来弄清这一点。我将使用相同的数据模型来简化操作。

用户有一个附加的“头像”。假设您拥有以下用户装置:

# 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

要计算校验和,请参见此处:

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 %>

请注意,您必须先将文件复制到存储目录中。