Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

write stream to paperclip

I want to store received email attachment with usage of paperclip. From email I get part.body and I have no idea how to put it to paperclip'ed model. For now I create temporary file and write port.body to it, store this file to paperclip, and delete file. Here is how I do it with temporary file:

    l_file = File.open(l_path, "w+b", 0644)
    l_file.write(part.body)
    oAsset = Asset.new(
        :email_id => email.id, 
        :asset => l_file, 
        :header => h, 
        :original_file_name => o, 
        :hash => h)
    oAsset.save
    l_file.close
    File.delete(l_path)

:asset is my 'has_attached_file' field. Is there a way to omit file creation and to do something like: :asset => part.body in Asset.new ?

like image 393
Mateusz Avatar asked Mar 02 '11 11:03

Mateusz


2 Answers

This is how I would do it, assuming your using the mail gem to read the email. you'll need the whole email 'part', not just part.body

file = StringIO.new(part.body) #mimic a real upload file
  file.class.class_eval { attr_accessor :original_filename, :content_type } #add attr's that paperclip needs
  file.original_filename = part.filename #assign filename in way that paperclip likes
  file.content_type = part.mime_type # you could set this manually aswell if needed e.g 'application/pdf'

now just use the file object to save to the Paperclip association.

a = Asset.new 
a.asset = file
a.save!

Hope this helps.

like image 176
David Barlow Avatar answered Oct 25 '22 19:10

David Barlow


Barlow's answer is good, but it is effectively monkey-patching the StringIO class. In my case I was working with Mechanize::Download#body_io and I didn't want to possibly pollute the class leading to unexpected bugs popping up far away in the app. So I define the methods on the instances metaclass like so:

original_filename = "whatever.pdf" # Set local variables for the closure below
content_type = "application/pdf"

file = StringIO.new(part.body)

metaclass = class << file; self; end
metaclass.class_eval do
  define_method(:original_filename) { original_filename }
  define_method(:content_type) { content_type }
end
like image 28
gtd Avatar answered Oct 25 '22 18:10

gtd