2010-07-20 12 views
117

Tengo persona modelo que tiene muchas imágenes, donde las imágenes tiene un campo de archivo adjunto Paperclip llamada de datos, una versión abreviada que se muestra a continuación: se requiere¿Cómo utilizo Factory Girl para generar un archivo adjunto de Paperclip?

class Person 
    has_many :images 
    ... 
end 

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

persona a tener al menos una imagen adjunta a la misma.

Al utilizar factorygirl, tengo código similar al siguiente:

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 También he probado el código comentado anteriormente también fue tratado) mayoría de las veces cuando corro características de pepino, yo obtendrá un error similar al siguiente:

No existe el fichero o directorio - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

A veces las pruebas se ejecutan correctamente.

¿Alguien me puede decir cuál es el problema que estoy teniendo aquí o cómo usan FactoryGirl y Paperclip juntos para lograr algo así como lo que estoy tratando de lograr?

estoy usando Rails 3.

+2

Hasta voto en cuestión solo por usar Keyzer Soze mientras prueba nombre! – Breno

+0

Lo que dijo @Breno ... –

+0

Cuando hago esto ... las fotos se generan y se colocan en la carpeta pública/del sistema cada vez que ejecuto el conjunto de pruebas. Las fotos no se destruyen después de que el banco de pruebas termine de ejecutarse. ¿Alguien más nota esto? – Jwan622

Respuesta

4

Trate de usar ActionController :: TestUploadedFile. Puede establecer la propiedad del archivo en una instancia de TestUploadedFile y paperclip debe encargarse del resto. Por ejemplo

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

¿Qué está probando exactamente? Ese clip de papel se adjuntará con éxito el archivo? Eso realmente parece una prueba que debe manejar el clip, no su aplicación.

Ha intentado

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

Utilizamos maquinista en lugar de factory_girl y acaba de utilizar cosas como

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

Aunque, en realidad no estamos probando mucho cuando hacemos esto, por lo general solo quiere tener un objeto válido Image.

+0

Tengo modelos que requieren una asociación válida con un modelo habilitado para Paperclip, con un archivo adjunto válido. – Eric

25

He estado usando el código en lo esencial a continuación:

Carriles 2

http://gist.github.com/162881

Rails 3

https://gist.github.com/313121

+1

Solo me pregunto las mismas cosas y esto funciona maravillosamente. Gracias. Lo puse en un inicializador. – Todd

+3

Obtuve un error 'stack_level_too_deep' con el fragmento de Rails 3. – dhulihan

+1

Algo a tener en cuenta: la esencia anterior usa la sintaxis FactoryGirl anterior. DanS Answer usa la nueva sintaxis. –

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

Esta es la solución funcional más simple. – superluminary

82

Puede utilizar fixture_file_upload

include ActionDispatch::TestProcess en su ayudante de prueba, aquí es una fábrica de ejemplo:

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

En el ejemplo anterior spec/photos/test.png, es necesario que existe en el directorio de aplicaciones root antes de ejecutar las pruebas.

+2

Esta respuesta es totalmente correcta, pero puede ser más claro decir que el TestProcess incluye necesidades que deben incluirse con Factory y no simplemente en su spec_helper. –

+2

Gracias por la aclaración, Andrew. También puede tener que colocar "incluir ActionDispatch :: TestProcess" antes del bloque FactoryGirl.define (que no es lo que sucede en este sentido: https://gist.github.com/313121). – Sam

+3

Además, se requiere el '{}'. Se rompe sin él – Edmund

44

reciente sintaxis FG y no incluye necesario

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

o, mejor aún,

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

Me gusta, pero tenga en cuenta que Rails 4 elimina la aplicación/assets/images/rails.png, por lo que tendrá que dar cuenta de ese cambio :) – stephenmurdoch

+0

Eso funciona, pero desafortunadamente las imágenes se cargan en/tmp – pmontrasio

37

Desmond Bowe encima en Pivotal Labs de suggests avoiding fixture_file_upload debido a problemas de pérdida de memoria. En su lugar, debe establecer los campos paperclip directamente en su fábrica:

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

Works para mi. También lo suficientemente simple como para no requerir un archivo existente en la carpeta de especificaciones/pruebas. – bibstha

+0

Fácil peezie, lemon squeezie !!!! –

+1

Además de evitar fugas de memoria, de esta manera las pruebas serán más rápidas. – evedovelli

0

Las respuestas anteriores en algunos casos pueden ayudar, y la que realmente ayudado en una de mis situaciones, pero cuando se utiliza una Carrierwave, la solución anterior de esta pregunta no funcionó esta vez.

primera aproximación:

Para mí la adición de un after :create resolvió el problema para mí de esta manera:

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

Configuración de archivo de vídeo en línea como video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") } no funcionó y se informa de los errores.

segundo enfoque:

definir una fábrica como esta (cambiar personal_file a su nombre de archivo adjunto):

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 

y añadir estas líneas al config/environemnts/test.rb:

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