ruby on rails inherit Como faço para usar Factory Girl para gerar um anexo de clipe de papel?




factorybot transient (7)

Eu tenho o modelo Person que tem muitas imagens, onde as imagens possuem um campo de anexo Paperclip chamado data, uma versão abreviada exibida abaixo:

class Person
  has_many :images
  ...
end

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

A pessoa é obrigada a ter pelo menos uma imagem anexada a ela.

Ao usar FactoryGirl, tenho código semelhante ao seguinte:

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 eu também tentei o código comentou acima também foi julgado) Na maioria das vezes quando eu executo recursos de pepino, recebo um erro semelhante ao seguinte:

Nenhum tal arquivo ou diretório - /tmp/stream9887,0.png (Errno :: ENOENT)

...

Às vezes, os testes são executados com sucesso.

Alguém pode me dizer qual é o problema que estou tendo aqui ou como eles usam FactoryGirl e Paperclip juntos para alcançar algo parecido com o que estou tentando alcançar?

Eu estou usando o Rails 3.


Desmond Bowe, do Pivotal Labs, sugere evitar o fixture_file_upload devido a problemas de vazamento de memória. Em vez disso, você deve definir os campos de clipe de papel diretamente em sua fábrica:

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

Tente usar ActionController :: TestUploadedFile. Você pode apenas definir a propriedade de arquivo para uma instância de TestUploadedFile e o clipe de papel deve cuidar do resto. Por exemplo

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

Sintaxe FG mais recente e não inclui

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

ou melhor ainda

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

Você pode usar fixture_file_upload

include ActionDispatch::TestProcess no seu auxiliar de teste, aqui está uma fábrica de exemplo:

include ActionDispatch::TestProcess

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

No exemplo acima, spec/photos/test.png precisa existir no diretório raiz do seu aplicativo antes de executar seus testes.

Note que FactoryBot é um novo nome para FactoryGirl .


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


As respostas acima, em alguns casos, podem ajudar, e a que realmente ajudou em uma das minhas situações, mas ao usar uma Carrierwave, a solução anterior desta questão não funcionou dessa vez.

PRIMEIRA ABORDAGEM:

Para mim adicionando um after :create resolveu o problema para mim assim:

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

Definir o arquivo de vídeo in-line como video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") } não funcionou e estava relatando erros.

SEGUNDA ABORDAGEM:

Defina uma fábrica como essa (altere personal_file para o nome do seu anexo):

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

E adicione estas linhas ao config/environemnts/test.rb :

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




factory-bot