ActionDispatch :: Http :: UploadedFile.content_type未在Rspec测试中初始化

rea*_*not 13 ruby rspec ruby-on-rails multipartform-data ruby-on-rails-4

背景:我有一个Book模型,其cover_file属性可以通过我的一个Rails控制器使用上传的文件进行设置.我正在使用Rails v4.0.4.

目标:我想测试只保存具有特定内容类型的文件.我计划使用ActionDispatch::Http:UploadedFile具有不同content_type属性的对象创建Rspec测试示例.

问题:当我ActionDispatch::Http::UploadedFile用a 初始化一个新的时content_type,它似乎没有被设置(参见下面的测试和输出确认它是零).似乎我只能在初始化UploadedFile之后用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
Run Code Online (Sandbox Code Playgroud)

输出:

true
image/jpeg
Run Code Online (Sandbox Code Playgroud)

rea*_*not 24

我查看了UploadedFile该类的Rails源文件,我发现了这个问题.例如,对于@content_type属性,当getter和setter命名为expected(.content_type)时,该initialize方法将查找typeoptions hash中调用的属性.@original_filename也会发生同样的事情; initialize查找filename而不是original_filename.这似乎是自Rails 3代码库以来的情况.

所以,如果我将上面的代码更改为以下内容,一切都按预期工作:

book.cover_file = ActionDispatch::Http::UploadedFile.new(tempfile: cover_image, filename: File.basename(cover_image), type: "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
Run Code Online (Sandbox Code Playgroud)