Ho ereditato un'app Rails 2.2.2 che memorizza le immagini caricate dall'utente su Amazon S3. Il modello attachment_fu basata Photo
offre un metodo che utilizza rotate
open-uri
per recuperare l'immagine da S3 e MiniMagick per effettuare la rotazione.Perché Ruby open-uri è aperto restituisce un StringIO nel mio test dell'unità, ma un FileIO nel mio controller?
Il metodo rotate
contiene questa linea per recuperare l'immagine da utilizzare con MiniMagick:
temp_image = MiniMagick::Image.from_file(open(self.public_filename).path)
self.public_filename
restituisce qualcosa come
http://s3.amazonaws.com/bucketname/photos/98/photo.jpg
Recupero l'immagine e ruotandola funzionano bene in applicazione in esecuzione in produzione e sviluppo. Tuttavia, il test fallisce con unità
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'
La ragione è che quando il metodo modello viene chiamata nel contesto del test di unità, open(self.public_filename)
restituisce un oggetto StringIO
che contiene i dati di immagine. Il metodo path
su questo oggetto restituisce nil
e MiniMagick::Image.from_file
colpi in su.
Quando questo stesso metodo di modello si chiama dal PhotosController
, open(self.public_filename)
restituisce un'istanza FileIO
legato ad un file chiamato, per esempio, /tmp/open-uri7378-0
e il file contiene i dati di immagine.
Pensando la causa deve essere una certa differenza tra l'ambiente di test e sviluppo, ho sparato la console sotto l'ambiente di sviluppo. Ma proprio come nel test di unità, open('http://...')
restituito un StringIO
, non un FileIO
.
Ho rintracciato la mia strada attraverso tutto il codice specifico dell'applicazione rilevanti open-uri e e riesco a trovare alcun motivo per la differenza.
Non fare 'open (self.public_filename) .read', non si sa quando l'handle verrà chiuso. Usa invece 'open (self.public_filename, &: read)', che usa il modulo di blocco e si chiude esplicitamente al termine. E non è più un codice. – apeiros
FYI, 'from_blob' è ora deprecato a favore di' read'. Vedi https://github.com/probablycorey/mini_magick/blob/f309fbf390cd21a845264bca9bec95b9bdae8029/lib/mini_magick.rb#L82 –