write stream to paperclip

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.


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

I like gtd's answer a lot, but it can be simpler.

file = StringIO.new(part.body)

class << file
  define_method(:original_filename) { "whatever.pdf" }
  define_method(:content_type) { "application/pdf" }
end

There's not really a need to extract the "metaclass" into a local variable, just append some class to the object.