Back

Explore Courses Blog Tutorials Interview Questions
0 votes
3 views
in AWS by (19.1k points)

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 open-uri to retrieve the image from S3 and MiniMagick to perform the rotation.

The rotate method contains this line to retrieve the image for use with MiniMagick:

temp_image = MiniMagick::Image.from_file(open(self.public_filename).path)

self.public_filename returns something like

http://s3.amazonaws.com/bucketname/photos/98/photo

Retrieving the image and rotating it works just fine in the running application in production and development. However, the unit test fails with

TypeError: can't convert nil into String

    /Users/santry/Development/totspot/vendor/gems/mini_magick-1.2.3/lib/mini_magick.rb:34:in `initialize'

    /Users/santry/Development/totspot/vendor/gems/mini_magick-1.2.3/lib/mini_magick.rb:34:in `open'

    /Users/santry/Development/totspot/vendor/gems/mini_magick-1.2.3/lib/mini_magick.rb:34:in `from_file'

The reason is that when the model method is called in the context of the unit test, open(self.public_filename) is returning a StringIO object that contains the image data. The path method on this object returns nil and MiniMagick::Image.from_file blows up.

When this very same model method is called from the PhotosController, open(self.public_filename) returns a FileIO instance tied to a file named, eg, /tmp/open-uri7378-0 and the file contains the image data.

Thinking the cause must be some environmental difference between test and development, I fired up the console under the development environment. But just as in the unit test, open('http://...') returned a StringIO, not a FileIO.

I've traced my way through open-uri and all the relevant application-specific code and can find no reason for the difference.

1 Answer

0 votes
by (44.4k points)

Using a common method for both classes will solve this issue, specifically the read method, with MiniMagick::Image#from_blob:

temp_image = MiniMagick::Image.from_blob(open(self.public_filename, &:read))

Related questions

0 votes
1 answer

Want to get 50% Hike on your Salary?

Learn how we helped 50,000+ professionals like you !

0 votes
1 answer
0 votes
1 answer

Browse Categories

...