viernes, 26 de marzo de 2010

Engañando al ojo

Enunciado: Dado un formulario Ajax con los campos Asunto y Contenido cuyo resultado es el envío de su contenido en un email, añadir un campo de tipo archivo para poder adjuntar documentos al mismo.

Bueno, pues lo primero es cambiar el formulario. Primero, reemplazamos la helper que lo genera de form_remote_tag a form_tag. Segundo, hacemos que su enctype sea "multipart/form-data". De esta forma permitimos adjuntar archivos a través del formulario. Y tercero, debajo del formulario creamos un iframe oculto donde enviar la petición del formulario para que parezca ajax.

<div style="overflow:hidden;width:0px;height:0px"><iframe id="hiddenIframe" name="hiddenIframe" src="" width="0" height="0"></iframe><div>

Lo siguiente es añadir un campo de tipo archivo. En rails

<%= file_field 'mail','attachment' %>

Probamos el envío para ver si nos llega al servidor lo que nos tiene que llegar y todo va bien. Así que ponemos en el evento onsubmit del formulario todos los efectos javascript que antes manejaba el helper form_remote_tag. Y todo se rompe. Y lo que leo en los logs y nada es lo mismo. Hasta que quito el efecto de deshabilitar el formulario en el evento onsubmit y todo vuelve a la normalidad. En fin, así es la vida. Sigamos.

En el controller hemos de recoger el parámetro que recoje el archivo adjunto y pasarlo tal cual al método que realiza el envío del archivo. Además, utilizaremos el plugin respond_to_parent para manejar la respuesta en el iframe oculto.

responds_to_parent do
 render :update do |page|
  ...
 end
end


La clase que realiza el envío debe crear con el archivo temporal un attachment pero como de un TempFile no se conoce su tipo (salvo si utilizamos algún plugin al uso), lo haremos de forma genérica. Siendo att la variable que contiene el archivo temporal...

filename = att.original_filename
filedata = att.read
attachment "application/octet-stream" do |a|
 a.body = filedata
 a.filename = filename
end


Y cuando parece que todo está listo, nos encontramos con una cosilla más. Resulta que cuando se adjuntan attachments no se ejecuta el render normal del email por lo que es necesario crear a mano un part con el contenido del correo y poner el content-type del correo a multipart/alternative. En el método de envío del correo, donde antes decía

@body[:content] = content

ahora debe decir

part :content_type => "text/html", :body => content

Y con esto y un bizcocho, todo funcionando. Espero que se entienda. ¡Salud y rocanrol!

Kick your ass to heaven
With rock'n'roll tonight
I'll make this night a special one
Make you feel alright
Shoot my heat into your body
Give you all my size
I'm gonna beat the beat tonight
It's time to break the ice
Dynamite


1 comentario:

danimataonrails dijo...

Olvidé mencionar que la información la fui sacando de aquí y aquí