PDFKit irreverencia y los monkey patches
Hace unos días, para un proyecto con un cliente, tuve la necesidad de poder generar archivos PDF a partir de que sus usuarios llenaran ciertos datos de una forma, para posteriormente y de forma automática, llenar un formato y permitirles descargarlo en PDF.
Para Ruby, hay varias opciones de hacer eso, por ejemplo esta Prawn, Wicked PDF y PDFKit, siendo las dos ultimas las mas sencillas de usar y que se ajustaban a mi necesidad, ya que con PDFkit, por ejemplo, puedo generar una vista en Rails y a partir de la vista generar mi PDF, por ejemplo de la siguiente forma:
Lo mejor de todo, es que PDFKit hace uso del motor de “rendereo” Webkit, el mismo de Chrome y Safari lo cual es un plus para crear formatos vistosos con html; esto es con la ayuda de wkhtmltopdf.
Hasta aquí todo parece esta muy bien, mi problema comenzó a tratar de generar mi primer formato, PDFKit me generaba un error, relacionado a que la llamada a wkhtmltopdf fallaba.
Todo parecia estar bien, pero no podía hacer que PDFKit me funcionara. Así, que siendo PDFKit OSS procedí a revisar el código fuente y ver si podía descubrir el problema. Navegando en el código llegue al culpable. El metodo to_pdf siempre me generaba error sin importar nada.
Resulta que to_pdf abre 2 pipes, un stdout y un stdin, uno para poder ejecutar el comando wkhtmltopdf con las opciones para la generación del pdf y el html a usar, otro para poder leer el resultado - que es el binario del pdf generado -, pero resulta que la lectura siempre viene vacía, aun y cuando wkhtmltopdf si genere el pdf. Después de revisar el código, no pude ver nada obvio que estuviese mal, pero no podía hacer que funcionara.
Así que me puse a reimplementar el metodo to_pdf, pero en lugar de usar exec, lo cambie a usar popen como se muestra a continuación.
Después de la redefinición del método to_pdf, PDFKit trabajo como debe, el parche aun no lo envío al autor de PDFKit y no se si lo aceptara o no, y no quiero terminar con mi propia versión de la gema en mi sistema, así que para poder usar PDFKit con mi cambio, me decidí a crear un MonkeyPatch, creando dentro del directorio de initializers de mi aplicación de Rails el archivo pdfkit.rb, donde hago una redefinición del método to_pdf cada que se inicializa mi aplicación, dejando de esta forma la gema original intacta.
Para saber mas sobre como funciona PDFKit, les recomiendo los siguientes sitios:
