【问题标题】:How Do I Use Factory Girl To Generate A Paperclip Attachment?如何使用 Factory Girl 生成回形针附件?
【发布时间】:2011-03-18 17:06:50
【问题描述】:

我的模型 Person 有很多图像,其中图像有一个称为数据的回形针附件字段,下面显示一个缩写版本:

class Person
  has_many :images
  ...
end

class Image
  has_attached_file :data
  belongs_to :person
  ...
end

此人必须至少附有一张图片。

使用 FactoryGirl 时,我的代码类似于以下内容:

Factory.define :image do |a|
  a.data { File.new(File.join(Rails.root, 'features', 'support', 'file.png')) }
  a.association :person
end

Factory.define :person do |p|
  p.first_name 'Keyzer'
  p.last_name 'Soze'
  p.after_create do |person|
    person.assets = [Factory.build(:image, :person => person)]
  end
  # p.images {|images| [images.association(:image)]}
end

(注:我也试过上面注释掉的代码也试过) 大多数时候,当我运行黄瓜功能时,我会收到类似于以下内容的错误:

没有这样的文件或目录 - /tmp/stream,9887,0.png (Errno::ENOENT)

...

有时测试会成功运行。

谁能告诉我我在这里遇到了什么问题,或者他们如何一起使用 FactoryGirl 和 Paperclip 来实现我想要实现的目标?

我正在使用 Rails 3。

【问题讨论】:

  • 对仅使用 Keyzer Soze 作为测试名称的问题进行投票!
  • 当我这样做时......每次运行测试套件时,照片都会生成并放置在 public/system 文件夹中。测试套件运行完成后,照片不会被破坏。有没有其他人注意到这一点?

标签: ruby-on-rails paperclip factory-bot


【解决方案1】:

尝试使用 ActionController::TestUploadedFile。您可以只将文件属性设置为 TestUploadedFile 的一个实例,而回形针应该负责其余的工作。例如

valid_file = File.new(File.join(Rails.root, 'features', 'support', 'file.png'))  
p.images { 
   [
     ActionController::TestUploadedFile.new(valid_file, Mime::Type.new('application/png'))
   ] 
}

【讨论】:

    【解决方案2】:

    您到底在测试什么?那个回形针会成功附加文件吗?这看起来确实像是回形针应该处理的测试,而不是您的应用程序。

    你试过了吗

    a.data { File.join(Rails.root, 'features', 'support', 'file.png') }
    

    我们使用 Machinist 而不是 factory_girl,并且刚刚使用过类似的东西

    Image.blueprint do
      image { RAILS_ROOT + 'spec/fixtures/images/001.jpg' }
    end
    

    虽然我们在执行此操作时并没有真正进行太多测试,但我们通常只想拥有一个有效的 Image 对象。

    【讨论】:

    • 我的模型需要与启用了回形针的模型有效关联,该模型本身带有有效附件。
    【解决方案3】:

    我一直在使用以下要点中的代码:

    导轨 2

    http://gist.github.com/162881

    轨道 3

    https://gist.github.com/313121

    【讨论】:

    • 只是想知道同样的事情,这很好用。谢谢。我把它放在初始化器中。
    • 注意事项:上面的要点使用较旧的 FactoryGirl 语法。 DanS 答案使用新语法。
    【解决方案4】:
    file { File.new(Rails.root.join('spec', 'fixtures', 'filename.png')) }
    

    【讨论】:

    • 这是最简单的功能解决方案。
    【解决方案5】:

    您可以使用fixture_file_upload

    include ActionDispatch::TestProcess 在您的测试助手中,这是一个示例工厂:

    include ActionDispatch::TestProcess
    
    FactoryBot.define do
      factory :user do
        avatar { fixture_file_upload(Rails.root.join('spec', 'photos', 'test.png'), 'image/png') }
      end
    end
    

    在上面的示例中,spec/photos/test.png 需要在运行测试之前存在于应用程序的根目录中。

    请注意,FactoryBotFactoryGirl 的新名称。

    【讨论】:

    • 这个答案是完全正确的,但可以更清楚地说 TestProcess 包含需要包含在工厂中,而不仅仅是在您的 spec_helper 中。
    • 感谢您的澄清,安德鲁。您可能还必须在 FactoryGirl.define 块之前放置“include ActionDispatch::TestProcess”(这不是本要点中发生的情况:gist.github.com/313121)。
    • 另外,{ } 是必需的。没有它就坏了
    • 进一步说明:include ActionDispatch::TestProcess 应该插入到工厂文件的最顶部,FactoryGirl.define do...end 块之外。
    【解决方案6】:

    较新的 FG 语法,不需要包含

    factory :user do
      avatar { File.new(Rails.root.join('app', 'assets', 'images', 'rails.png')) }
    end
    

    或者,更好的是,

    factory :user do
      avatar { File.new("#{Rails.root}/spec/support/fixtures/image.jpg") } 
    end
    

    【讨论】:

    • 我喜欢它,但请记住,rails 4 删除了 app/assets/images/rails.png,因此您需要考虑该更改 :)
    【解决方案7】:

    由于内存泄漏问题,Desmond Bowe 在 Pivotal Labs suggests avoiding fixture_file_upload 工作。相反,您应该直接在工厂中设置回形针字段:

    factory :attachment do
      supporting_documentation_file_name { 'test.pdf' }
      supporting_documentation_content_type { 'application/pdf' }
      supporting_documentation_file_size { 1024 }
      # ...
    end
    

    【讨论】:

    • 为我工作。也很简单,不需要 spec/test 文件夹中的现有文件。
    • 除了避免内存泄漏,这样测试会更快。
    • 上述博文移至pivotal.io/blog
    • 不幸的是,这不适用于content_type 上的附件验证。为此,您需要一个有效的文件对象。
    【解决方案8】:

    在某些情况下,上述答案可能会有所帮助,并且在我的一种情况下实际上有所帮助,但是当使用载波时,这个问题的先前解决方案这次没有解决。

    第一种方法:

    对我来说,添加after :create 为我解决了这样的问题:

    after :create do |b|
      b.update_column(:video_file, File.join(Rails.root, 'spec', 'fixtures', 'sample.mp4'))
    end
    

    设置像video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }这样的内联视频文件没有成功,它正在报告错误。

    第二种方法:

    像这样定义一个工厂(将personal_file更改为您的附件名称):

    FactoryGirl.define do
      factory :contact do
        personal_file { File.new("#{Rails.root}/spec/fixtures/personal_files/my_test_file.csv") }
        personal_file_content_type 'text/csv'
    
      end
    end
    

    并将这些行添加到config/environemnts/test.rb

    config.paperclip_defaults = {
      url: "#{Rails.root}/spec/fixtures/:attachment/:filename",
      use_timestamp: false
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多