背景:我有一个具有cover_file属性的Book模型,通过我的Rails控制器之一设置上传的文件.我使用的是Rails v4.0.4.
目标:我想测试只有具有某些内容类型的文件被保存.我计划使用ActionDispatch :: Http:UploadedFile对象设置不同的content_type属性来创建Rspec测试示例.
问题:当我使用content_type初始化一个新的ActionDispatch :: Http :: UploadedFile时,它似乎没有设置(参见下面的测试&输出,确认它是零).似乎我只能在已经初始化了UploadFile之后用setter设置它.我没有在文档中提到这种行为,也没有在SO上找到类似的问答,所以我感谢任何人的帮助来确定我做错了什么.谢谢!
码:
describe Book do let(:book) {FactoryGirl.build(:book)} describe "Save" do context "with valid data" do before do cover_image = File.new(Rails.root + 'spec/fixtures/images/cover_valid.jpg') book.cover_file = ActionDispatch::Http::UploadedFile.new(tempfile: cover_image,filename: File.basename(cover_image),content_type: "image/jpeg") puts book.cover_file.content_type.nil? book.cover_file.content_type = "image/jpeg" puts book.cover_file.content_type end specify{expect(book.save).to be_true} end end end
输出:
true image/jpeg
解决方法
我查看了有关UploadFile类的Rails源文件,我发现了这个问题.对于@content_type属性,例如,当getter和setter被命名为expected(.content_type)时,initialize方法在options hash中查找一个名为type的属性.同样的事情发生在@original_filename;初始化查找文件名而不是original_filename.这似乎是Rails 3代码库以来的情况.
所以,如果我将我的代码更改为以下内容,一切都按预期方式工作:
book.cover_file = ActionDispatch :: Http :: UploadedFile.new(tempfile:cover_image,filename:File.basename(cover_image),键入:“image / jpeg”)
rails / actionpack / lib / action_dispatch / http / upload.rb的相关章节
class UploadedFile # The basename of the file in the client. attr_accessor :original_filename # A string with the MIME type of the file. attr_accessor :content_type # A +Tempfile+ object with the actual uploaded file. Note that some of # its interface is available directly. attr_accessor :tempfile alias :to_io :tempfile # A string with the headers of the multipart request. attr_accessor :headers def initialize(hash) # :nodoc: @tempfile = hash[:tempfile] raise(ArgumentError,':tempfile is required') unless @tempfile @original_filename = encode_filename(hash[:filename]) @content_type = hash[:type] @headers = hash[:head] end