Làm cách nào để sử dụng Factory Girl để tạo tệp đính kèm kẹp giấy?


119

Tôi có mô hình Người có nhiều Hình ảnh, trong đó hình ảnh có trường đính kèm Kẹp giấy được gọi là dữ liệu, phiên bản viết tắt được hiển thị bên dưới:

class Person
  has_many :images
  ...
end

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

Người được yêu cầu phải có ít nhất một Hình ảnh đính kèm với nó.

Khi sử dụng FactoryGirl, tôi có mã tương tự như sau:

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 Tôi cũng đã thử mã nhận xét ở trên cũng đã được thử) Hầu hết thời gian khi tôi chạy các tính năng dưa chuột, tôi gặp lỗi tương tự như sau:

Không có tệp hoặc thư mục nào như vậy - /tmp/stream,9887,0.png (Errno :: ENOENT)

...

Đôi khi các bài kiểm tra chạy thành công.

Có ai có thể cho tôi biết vấn đề mà tôi đang gặp phải ở đây hay cách họ sử dụng FactoryGirl và Paperclip với nhau để đạt được điều gì đó giống như những gì tôi đang cố gắng đạt được không?

Tôi đang sử dụng Rails 3.


2
Bỏ phiếu cho câu hỏi chỉ vì sử dụng Keyzer Soze làm tên thử nghiệm!
Breno

Khi tôi làm điều này ... ảnh được tạo và đặt trong thư mục công khai / hệ thống mỗi khi tôi chạy bộ thử nghiệm. Ảnh không bị phá hủy sau khi chạy xong bộ thử nghiệm. có ai chú ý việc này không?
Jwan622,

Câu trả lời:


86

Bạn có thể sử dụng fixture_file_upload

include ActionDispatch::TestProcess trong trình trợ giúp thử nghiệm của bạn, đây là một nhà máy mẫu:

include ActionDispatch::TestProcess

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

Trong ví dụ trên, spec/photos/test.pngcần phải tồn tại trong thư mục gốc của ứng dụng trước khi chạy các bài kiểm tra của bạn.

Lưu ý, đó FactoryBotlà một tên mới cho FactoryGirl.


2
Câu trả lời này hoàn toàn đúng nhưng có thể rõ ràng hơn khi nói rằng bao gồm TestProcess cần phải được bao gồm trong Factory chứ không chỉ đơn giản trong spec_helper của bạn.
Andrew Hubbs

2
Cảm ơn vì đã làm rõ, Andrew. Bạn cũng có thể phải đặt "include ActionDispatch :: TestProcess" trước khối FactoryGirl.define (không phải là những gì xảy ra trong ý chính này: gist.github.com/313121 ).
Sam

3
Ngoài ra, { }được yêu cầu. Nó phá vỡ mà không có nó
bigpotato

3
Làm rõ thêm: các include ActionDispatch::TestProcessnên được chèn ở đầu rất của tập tin máy, bên ngoài các FactoryGirl.define do...endkhối.
Frank Koehl

49

Cú pháp FG mới hơn và không cần bao gồm

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

hoặc tốt hơn,

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

2
Tôi thích nó, nhưng hãy nhớ rằng đường ray 4 để loại bỏ việc ứng dụng / tài sản / images / rails.png, vì vậy bạn sẽ cần phải tài khoản cho sự thay đổi đó :)
stephenmurdoch

38

Desmond Bowe tại Pivotal Labs đề xuất tránh fixture_file_upload do sự cố rò rỉ bộ nhớ. Thay vào đó, bạn nên đặt các trường kẹp giấy trực tiếp trong nhà máy của mình:

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

Làm việc cho tôi. Cũng đủ đơn giản để không yêu cầu tệp hiện có trong thư mục spec / test.
bibstha

2
Bên cạnh việc tránh rò rỉ bộ nhớ, bằng cách này, các bài kiểm tra sẽ nhanh hơn.
evedovelli

Bài đăng trên blog được đề cập đã chuyển đến pivotal.io/blog
Karsten S.

Rất tiếc, điều này không hoạt động khi bật xác thực tệp đính kèm content_type. Đối với điều đó, bạn cần một đối tượng tệp hợp lệ.
Karsten S.

25

Tôi đã sử dụng mã trong ý chính bên dưới:

Đường ray 2

http://gist.github.com/162881

Đường ray 3

https://gist.github.com/313121


1
Chỉ cần tự hỏi những điều tương tự và điều này hoạt động tuyệt vời. Cảm ơn. Tôi đặt nó trong một trình khởi tạo.
Todd

1
Một điều cần lưu ý: Ý chính ở trên sử dụng cú pháp FactoryGirl cũ hơn. Câu trả lời của DanS sử dụng cú pháp mới.
Andrew Hubbs


4

Hãy thử sử dụng ActionController :: TestUploadedFile. Bạn chỉ có thể đặt thuộc tính tệp thành một phiên bản của TestUploadedFile và kẹp giấy sẽ đảm nhận phần còn lại. Ví dụ

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

0

Các câu trả lời trên trong một số trường hợp có thể hữu ích và câu trả lời thực sự hữu ích trong một trong những tình huống của tôi, nhưng khi sử dụng Carrierwave, lần này giải pháp trước cho câu hỏi này đã không thành công.

CÁCH TIẾP CẬN ĐẦU TIÊN:

Đối với tôi, thêm một after :createvấn đề đã giải quyết cho tôi như thế này:

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

Đặt tệp video nội tuyến như video_file { File.new("#{Rails.root}/spec/fixtures/sample.mp4") }không hoạt động và nó đang báo lỗi.

CÁCH TIẾP CẬN THỨ HAI:

Xác định một nhà máy như thế này (thay đổi personal_filethành tên tệp đính kèm của bạn):

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

Và thêm những dòng này vào config/environemnts/test.rb:

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

-1

Bạn đang thử nghiệm chính xác những gì? Kẹp giấy đó sẽ đính kèm tập tin thành công? Điều đó thực sự có vẻ giống như một bài kiểm tra mà kẹp giấy sẽ xử lý, không phải ứng dụng của bạn.

Bạn đã thử chưa

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

Chúng tôi sử dụng Machinist thay vì factory_girl và chỉ sử dụng những thứ như

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

Mặc dù vậy, chúng tôi không thực sự kiểm tra nhiều khi làm điều này, chúng tôi thường chỉ muốn có một Imageđối tượng hợp lệ .


Tôi có các mô hình yêu cầu liên kết hợp lệ với mô hình hỗ trợ Kẹp giấy, bản thân nó có tệp đính kèm hợp lệ.
Eric
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.