El problema: ActiveResource es muy bueno para hacer que dos aplicaciones
de Rails se comuniquen satisfactoriamente, sin embargo, una vez que se
habla de file uploads y de soporte para multipart, la cosa se complica
un poco, ya que ActiveResource no tien soporte para esto.
Contexto: Railsy-fu es una aplicacion que usa el plugin attachment-fu
para poder hacer file uploads. (Ver el post anterior). RailsyResource es
una aplicacion que usa los web services de de Railsy-fu. RailsyResource
es la que se va a encargar de hacer los file uploads.
En este ejemplo, una mensaje puede o no tener un attachment. Vamos a
tener que primero hacer el upload a Railsy-fu y después tomar el id de
ese file para relacionarlo con la aplicación.
Como no podemos usar ActiveResource, vamos a tener que hacer un post
desde RailsyResource a Railsy-fu con multipart. Para poder hacer esto,
existe la ‘gem httpclient’. (Instalarla… gem i httpclient).
El procedimiento es asi…
1) Instanciamos el objeto Httpclient
clnt = HTTPClient.new
2) El archivo que se va a ser uploaded, tiene un filename del tipo
RackMultipart0123456789 y se encuentra en /tmp/ comúnmente. Como es un
archivo temporal, no podemos renombrarlo ahi mismo en /tmp/ , entonces
debemos de copiar el archivo a una carpeta temporal dentro del
RAILS_ROOT
name = params[:message][:file].original_filename
directory = "#{RAILS_ROOT}/public/temp/"
path = File.join(directory, name)
File.open(path, "w+") { |f| f.write(params[:message][:file].read) }
3) Ya que ha sido creado el archivo con su nombre original, lo mandamos
por post/put a el web service de Railsy-fu.
body = { :uploaded_data => File.open("#{RAILS_ROOT}/public/temp/" + name), :message => ‘yeah!!!’, :apikey => ‘12312312312312312123123′}
res = clnt.post(’http://railsyfu.com/files.xml’, body)
4) Necesitaremos el file_id de ese archivo que acabamos de guardar para
poder relacionarlo con el objeto. Para hacer esto vamos a parsear el
response (con libxml-ruby, es más rápido según esto).
doc = XML::Document.string(res.content)
file_id = doc.root.find_first(’id’).content #por ejemplo <id> 145 </id>
5) Y se lo anhadimos al objeto message.
@message.file_id = file_id
Falta despues hacer revisar si es que se no se hizo un attachment, asi
que todo lo anterior deberia de estar dentro de un if que hace esta
verificacion.
Por ultimo, borramos el archivo temporal que hicimos.
if @message.save
File.delete("#{RAILS_ROOT}/public/temp/" + name) if params[:message][:file] and File.exists?("#{RAILS_ROOT}/public/temp/" + name)