Why does Ruby open-uri's open return a StringIO in my unit test, but a FileIO in my controller?

前端 未结 3 705
梦谈多话
梦谈多话 2020-12-24 06:43

I inherited a Rails 2.2.2 app that stores user-uploaded images on Amazon S3. The attachment_fu-based Photo model offers a rotate method that uses <

相关标签:
3条回答
  • 2020-12-24 06:55

    The open-uri library uses a constant to set the 10KB size limit for StringIO objects.

    > OpenURI::Buffer::StringMax
    => 10240 
    

    You can change this setting to 0 to prevent open-uri from ever creating a StringIO object. Instead, this will force it to always generate a temp file.

    Just throw this in an initializer:

    # Don't allow downloaded files to be created as StringIO. Force a tempfile to be created.
    require 'open-uri'
    OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax')
    OpenURI::Buffer.const_set 'StringMax', 0
    

    You can't just set the constant directly. You need to actually remove the constant and then set it again (as above), otherwise you'll get a warning:

    warning: already initialized constant StringMax
    

    UPDATED 12/18/2012: Rails 3 doesn't require OpenURI by default, so you need to add require 'open-uri' at the top of the initializer. I updated the code above to reflect that change.

    0 讨论(0)
  • 2020-12-24 07:01

    The code responsible for this is in the Buffer class in open-uri. It starts by creating a StringIO object and only creates an actual temp file in the local filesystem when the data exceeds a certain size (10 KB).

    I assume that whatever data your test is loading is small enough to be held in a StringIO and the images you are using in the actual application are large enough to warrant a TempFile. The solution is to use methods which are common to both classes, in particular the read method, with MiniMagick::Image#from_blob:

    temp_image = MiniMagick::Image.from_blob(open(self.public_filename, &:read))
    
    0 讨论(0)
  • 2020-12-24 07:11

    Now OpenURI::Buffer::StringMax can be set directly:

    require 'open-uri'
    OpenURI::Buffer::StringMax = 0
    

    but with a warning:

    warning: already initialized constant OpenURI::Buffer::StringMax
    
    0 讨论(0)
提交回复
热议问题