ファクトリーガールを使用してクリップの添付ファイルを生成するにはどうすればよいですか?


119

私は多くの画像を持つモデルPersonを持っています。ここで、画像にはdataというペーパークリップ添付フィールドがあり、その簡略版は以下に表示されています。

class Person
  has_many :images
  ...
end

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

少なくとも1つの画像を添付する必要があります。

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を使用しています。


2
名前をテストするときにKeyzer Sozeを使用するだけの質問に賛成票を投じてください!
Breno、2014

これを行うと、テストスイートを実行するたびに写真が生成され、public / systemフォルダーに配置されます。テストスイートの実行が終了しても、写真は破棄されません。他の誰かがこれに気付いていますか
Jwan622

回答:


86

あなたは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は、テストを実行する前に、アプリケーションのルートディレクトリに存在する必要があります。

これFactoryBotはの新しい名前ですFactoryGirl


2
この答えは完全に正しいですが、TestProcessインクルードは、単にspec_helper内ではなく、Factoryに含める必要があると言う方が明確かもしれません。
Andrew Hubbs 2012年

2
説明してくれてありがとう、アンドリュー。また、FactoryGirl.defineブロックの前に「include ActionDispatch :: TestProcess」を配置する必要がある場合もあります(これは、この要点gist.github.com/313121では発生しません)。
サム

3
また、{ }必須です。それなしで壊れる
bigpotato 2013年

3
詳細説明:include ActionDispatch::TestProcessは、ファクトリファイルの最上部、ブロックのに挿入する必要がありFactoryGirl.define do...endます。
フランクケール2014

49

新しい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

2
私はそれが好きですが、rails 4はapp / assets / images / rails.pngを削除するので、その変更を考慮する必要があることを
覚えておい

38

Pivotal LabsのDesmond Boweは、メモリリークの問題のために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フォルダーに既存のファイルを必要としないほど簡単です。
Bibstha 14

2
メモリリークを回避することに加えて、この方法ではテストが高速になります。
evedovelli 2016年

言及されたブログ投稿は、pivotal.io /
Karsten S.

残念ながら、これはの添付ファイル検証では機能しませんcontent_type。そのためには、有効なファイルオブジェクトが必要です。
Karsten S.



4

ActionController :: TestUploadedFileを使用してみてください。fileプロパティをTestUploadedFileのインスタンスに設定するだけで、あとはpaperclipが処理します。例えば

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

0

上記の回答が役立つ場合もあれば、実際に私の状況の1つで役立つ場合もありますが、Carrierwaveを使用している場合、この質問の以前の解決策は今回はうまくいきませんでした。

最初のアプローチ:

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") }しても機能せず、エラーが報告されていました。

2番目のアプローチ:

次のようにファクトリを定義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
}

-1

正確に何をテストしていますか?そのクリップはファイルを正常に添付しますか?これは、アプリケーションではなく、ペーパークリップで処理する必要があるテストのようです。

やってみました

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

私たちは、factory_girlの代わりにMachinistを使用し、

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

ただし、これを行うときはあまりテストしていませんが、通常は有効なImageオブジェクトが必要なだけです。


Paperclip対応モデルとの有効な関連付けを必要とするモデルがあり、それ自体に有効なアタッチメントがあります。
Eric
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.