Как да използвам Factory Girl за генериране на прикачен файл за кламер?

Имам модел 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

(N.B. Аз също опитах кода, коментиран по-горе, също беше изпробван) През повечето време, когато стартирам функции на краставица, получавам грешка, подобна на следното:

Няма такъв файл или директория - /tmp/stream,9887,0.png (Errno::ENOENT)

...

Понякога тестовете протичат успешно.

Може ли някой да ми каже какъв е проблемът, който имам тук или как използват FactoryGirl и Paperclip заедно, за да постигнат нещо като това, което се опитвам да постигна?

Използвам Rails 3.


person Laz    schedule 20.07.2010    source източник
comment
Гласувайте за въпрос само за използването на Keyzer Soze като тестово име!   -  person Breno    schedule 01.08.2014
comment
Когато правя това... снимките се генерират и поставят в публичната/системна папка всеки път, когато стартирам тестовия пакет. Снимките не се унищожават, след като тестовият пакет приключи. Някой друг забелязва ли това?   -  person Jwan622    schedule 10.01.2016


Отговори (8)


Можете да използвате 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.

person DanS    schedule 02.04.2012
comment
Този отговор е напълно правилен, но може да е по-ясно да се каже, че включването на TestProcess трябва да бъде включено във Factory, а не просто във вашия spec_helper. - person Andrew Hubbs; 23.10.2012
comment
Благодаря за пояснението, Андрю. Може също да се наложи да поставите включване ActionDispatch::TestProcess преди блока FactoryGirl.define (което не се случва в тази същност: gist.github.com/313121). - person Sam; 24.12.2012
comment
Освен това { } са задължителни. Чупи се и без него - person bigpotato; 18.10.2013
comment
Допълнително пояснение: include ActionDispatch::TestProcess трябва да се вмъкне най-отгоре на фабричния файл, извън блока FactoryGirl.define do...end. - person Frank Koehl; 23.04.2014

По-нов синтаксис на 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
person Neal    schedule 28.06.2013
comment
Харесва ми, но имайте предвид, че rails 4 премахва app/assets/images/rails.png, така че ще трябва да отчетете тази промяна :) - person stephenmurdoch; 06.08.2013

Дезмънд Боу от Pivotal Labs предлага избягване на fixture_file_upload поради проблеми с изтичане на памет. Вместо това трябва да зададете полетата за кламер директно във вашата фабрика:

factory :attachment do
  supporting_documentation_file_name { 'test.pdf' }
  supporting_documentation_content_type { 'application/pdf' }
  supporting_documentation_file_size { 1024 }
  # ...
end
person Rick Quantz    schedule 21.11.2013
comment
Работи за мен. Също така достатъчно просто, за да не изисква съществуващ файл в папката spec/test. - person Bibek Shrestha; 01.07.2014
comment
Освен избягване на изтичане на памет, по този начин тестовете ще бъдат по-бързи. - person evedovelli; 27.11.2016
comment
Споменатата публикация в блога се премести в основен. io/блог - person Karsten S.; 22.03.2017
comment
За съжаление това не работи с валидирането на прикачени файлове на content_type. За целта ви трябва валиден файлов обект. - person Karsten S.; 22.03.2017

Използвах кода в същността по-долу:

Релси 2

http://gist.github.com/162881

Релси 3

https://gist.github.com/313121

person deb    schedule 02.08.2010
comment
Просто се чудя на същите неща и това работи прекрасно. Благодаря. Сложих го в инициализатор. - person Todd; 20.11.2010
comment
Нещо за отбелязване: Същността по-горе използва по-стария синтаксис на FactoryGirl. DanS отговорът използва новия синтаксис. - person Andrew Hubbs; 23.10.2012

Опитайте да използвате 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'))
   ] 
}
person britt    schedule 22.07.2010

Горните отговори в някои случаи могат да помогнат и този всъщност помогна в една от моите ситуации, но при използване на 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") } не проработи и отчиташе грешки.

ВТОРИ ПОДХОД:

Дефинирайте фабрика като тази (променете 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
}
person Aleks    schedule 29.12.2016

Какво точно тествате? Този кламер ще прикачи ли успешно файла? Това наистина изглежда като тест, с който трябва да се справи кламерът, а не вашето приложение.

Опитахте ли

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 обект.

person theIV    schedule 22.07.2010
comment
Имам модели, които изискват валидна асоциация с активиран за кламер модел, сам по себе си с валиден прикачен файл. - person Eric; 29.12.2011

person    schedule
comment
Това е най-простото функционално решение. - person superluminary; 12.10.2012