31

ユーザーがアップロードした画像を A​​mazon S3 に保存する Rails 2.2.2 アプリを継承しました。attachment_fu ベースのPhotoモデルは、S3 と MiniMagick から画像を取得して回転を実行するrotateメソッドを提供します。open-uri

このrotateメソッドには、MiniMagick で使用する画像を取得する次の行が含まれています。

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

self.public_filenameのようなものを返します

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

画像を取得して回転させることは、運用中および開発中の実行中のアプリケーションで問題なく機能します。ただし、単体テストは失敗します

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'

その理由は、単体テストのコンテキストでモデル メソッドが呼び出されると、画像データを含むオブジェクトopen(self.public_filename)が返されるためです。このオブジェクトのメソッドが戻っStringIOて爆発します。pathnilMiniMagick::Image.from_file

このまったく同じモデル メソッドが から呼び出されると、 は、eg という名前のファイルに関連付けられたインスタンスPhotosControlleropen(self.public_filename)返します。このファイルには画像データが含まれています。FileIO/tmp/open-uri7378-0

テスト環境と開発環境の違いが原因かと思い、開発環境でコンソールを立ち上げてみました。しかし、単体テストと同様に、ではなくopen('http://...')を返しました。StringIOFileIO

open-uri と関連するすべてのアプリケーション固有のコードをたどりましたが、違いの理由は見つかりません。

4

3 に答える 3

74

open-uri ライブラリは、定数を使用して StringIO オブジェクトのサイズ制限を 10KB に設定します。

> OpenURI::Buffer::StringMax
=> 10240 

この設定を 0 に変更して、open-uri が StringIO オブジェクトを作成しないようにすることができます。代わりに、これにより常に一時ファイルが生成されます。

これを初期化子に投げるだけです:

# 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

定数を直接設定することはできません。実際に定数を削除してから、(上記のように) 再度設定する必要があります。そうしないと、警告が表示されます。

warning: already initialized constant StringMax

UPDATED 12/18/2012 : Rails 3 はデフォルトで OpenURI を必要としないためrequire 'open-uri'、初期化子の先頭に追加する必要があります。その変更を反映するために上記のコードを更新しました。

于 2011-07-09T01:05:35.037 に答える