web-dev-qa-db-ja.com

ファクトリーガールを使用してペーパークリップの添付ファイルを生成する方法

私は多くの画像を持っているモデルPersonを持っています。画像には、データと呼ばれるPaperclip添付フィールドがあり、以下に簡略版が表示されています。

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

(N.B.上記のコメントアウトされたコードも試しました)キュウリ機能を実行すると、ほとんどの場合、次のようなエラーが発生します:

そのようなファイルまたはディレクトリはありません-/tmp/stream,9887,0.png(Errno :: ENOENT)

...

テストが正常に実行される場合があります。

誰が私がここで抱えている問題なのか、または彼らがFactoryGirlとPaperclipを一緒に使用して私が達成しようとしているようなものを達成する方法を教えてもらえますか?

私はRails 3。

118
Laz

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の新しい名前であることに注意してください。

84
DanS

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

Pivotal LabsのDesmond Bowe氏 fixture_file_uploadを回避する提案 メモリリークの問題のため。代わりに、工場でPaperclipフィールドを直接設定する必要があります。

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

私は以下の要点のコードを使用しています:

Rails 2

http://Gist.github.com/162881

Rails 3

https://Gist.github.com/313121

25
deb
file { File.new(Rails.root.join('spec', 'fixtures', 'filename.png')) }
12
Matthew Deiters

ActionController :: TestUploadedFileを使用してみてください。ファイルプロパティを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'))
   ] 
}
4
britt

上記の回答はいくつかの場合に役立ち、私の状況の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
_

そして、これらの行をthe _config/environemnts/test.rb_に追加します:

_config.Paperclip_defaults = {
  url: "#{Rails.root}/spec/fixtures/:attachment/:filename",
  use_timestamp: false
}
_
0
Aleks