2010-07-20 2 views
117

У меня есть модель Людей, который имеет много изображений, где изображения имеют поле вложения Paperclip под названием данные, сокращенная версия отображается ниже:Как использовать заводскую девушку для создания приложения для скрепки скрепки?

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 

(NB Я также попробовал код комментировал выше также пытался) Большую часть времени, когда я бегу особенности огурца, я получаю сообщение об ошибке, похожее на следующее:

Нет такого файла или каталога - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

Иногда тесты проходят успешно.

Может ли кто-нибудь сказать мне, в чем проблема: у меня есть или как они используют FactoryGirl и Paperclip вместе, чтобы достичь чего-то вроде того, чего я пытаюсь достичь?

Я использую Rails 3.

+2

Up голос на вопрос только для использования Keyzer Soze, когда вы тестируете имя! – Breno

+0

Что сказал @Breno ... –

+0

Когда я это делаю ... фотографии генерируются и размещаются в общедоступной/системной папке каждый раз, когда я запускаю набор тестов. Фотографии не будут уничтожены после завершения набора тестов. Кто-нибудь еще замечает это? – Jwan622

ответ

4

Попробуйте использовать 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')) 
    ] 
} 
-1

Что вы точно тестируете? Эта скрепка будет успешно прикреплять файл? Это действительно похоже на тест, который должен обрабатывать скрепка, а не ваше приложение.

Вы пробовали

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

Мы используем вместо Машинист factory_girl и просто использовали такие вещи, как

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

Хотя, мы на самом деле не испытывать много, когда мы делаем это, мы, как правило, только хотите иметь действительный объект Image.

+0

У меня есть модели, которые требуют правильной связи с моделью с поддержкой скрепки скрепки, которая сама по себе имеет действующее приложение. – Eric

25

Я использую код в сущности ниже:

Rails 2

http://gist.github.com/162881

Rails 3

https://gist.github.com/313121

+1

Просто интересно то же самое, и это прекрасно работает. Благодарю. Я положил его в инициализатор. – Todd

+3

Получил ошибку 'stack_level_too_deep' с фрагментом Rails 3. – dhulihan

+1

Что-то примечание: Суть выше использует более старый синтаксис FactoryGirl. Ответ DanS использует новый синтаксис. –

11
file { File.new(Rails.root.join('spec', 'fixtures', 'filename.png')) } 
+0

Это простейшее функциональное решение. – superluminary

82

Вы можете использовать fixture_file_upload

include ActionDispatch::TestProcess в проверяемом помощнике, вот пример завод:

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

В приведенном выше примере, spec/photos/test.png необходимо существует в корневом каталоге приложения перед запуском тестов.

+2

Этот ответ абсолютно прав, но может быть более понятным сказать, что включение TestProcess должно быть включено в Factory, а не просто в spec_helper. –

+2

Спасибо за разъяснение, Андрей. Возможно, вам также придется добавить «Включить ActionDispatch :: TestProcess» перед блоком FactoryGirl.define (что не происходит в этом контексте: https://gist.github.com/313121). – Sam

+3

Кроме того, требуется '{}'. Он обрывается без него. – Edmund

44

Новее 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

Мне это нравится, но имейте в виду, что рельсы 4 удаляют app/assets/images/rails.png, поэтому вам нужно будет учитывать это изменение :) – stephenmurdoch

+0

Это работает, но, к сожалению, изображения загружаются в/tmp – pmontrasio

37

Desmond Его над на Pivotal Labs suggests avoiding 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 
+0

Works для меня. Также достаточно просто, чтобы не требовать наличия существующего файла в папке spec/test. – bibstha

+0

Легкое peezie, лимонное squeezie !!!! –

+1

Кроме того, чтобы избежать утечек памяти, таким образом, тесты будут быстрее. – evedovelli

0

Вышеуказанные ответы в некоторых случаях могут помочь, и тот на самом деле помог в одном из моих ситуаций, но при использовании 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 
}