Blog sobre desarrollo de software

Ver más

Hacer el despliegue -deployment -de una aplicación Rails a la Heroku

Ya en varias ocasiones, durante platicas o reuniones relacionadas con Ruby y con Rails, me han preguntado como hacer el despliegue de una aplicación Web hacia un servidor Linux. Generalmente mi respuesta rapida es “no te metas en problema, usa Heroku”.

La recomendación de Heroku es porque no nos tenemos que preocupar de instalar ni configurar nada, solo hacemos un push de nuestro repositorio Git y el proceso de Heroku se encarga de configurar todo para tener nuestra aplicación funcionando desde Internet en cuestión de minutos.

El “detalle” con Heroku, como me han comentado, es que cuesta, me dicen, “yo lo que quiero es configurar mi propio servidor linux y ejecutar la aplicación desde ahi”. Bueno en este caso, hay muchas “recetas” de como hacerle.

Generalmente todas estas “recetas” requieren de pasos de instalación de programas y librerías como servidor web, motor de base de datos, herramientas adicionales, etc. para dejar nuestro ambiente preparado para poder desplegar nuestra aplicación web.

Cuando finalmente tenemos nuestro entorno listo, el siguiente paso es configurar Capistrano, el cual requiere de una “receta” con los pasos a realizar para desplegar la aplicación a un servidor remoto. Estos pasos incluyen instrucciones por ejemplo de a que repositorio git conectarse para tener el código fuente, realizar migraciones de base de datos, ejecutar pasos adicionales de configuración etc.

Es algo feasible, pero requiere de un poco de esfuerzo y quizas un poco de frustraciones de vez en cuando, hasta que tenemos una solución que nos agrada para el despliegue de la aplicaciones la primera vez y los cambios subsecuentes.

Hace un par de dias, y por casi casualidad me tope con Gitpusshuten, el cual es una herramienta para hacer el despliegue de aplicaciones Ruby/Rails.

Lo interesante de Gitpusshuten es que hace que el proceso de despliegue a servidores Linux sea casi tan simple como lo hace Heroku.

Gitpusshuten inclusive puede instalar y configurar todo el software y herramientas necesarias para que nuestro servidor Linux funcione como Webserver, aun si nuestro servidor es una nueva instalación.

Definitivamente si están buscan opciones para montar sus propios servidores Linux y desplegar desde ahi las aplicaciones Ruby/Rails deben de darle una revisada a Gitpusshuten, ya que en cuestión de minutos les ayudara a tener su aplicación en linea funcionado.

Video de Webinar para JoeDayz sobre Ruby On Rails

El pasado 8 de febrero a invitación de JoeDayz presente un Webinar sobre Ruby On Rails. La presentación fue grabada y el video se puede descargar desde la pagina de JoeDayz.

El unico detalle con la grabación, es que esta codificada en Windows Media con el codec exclusivo de GoToMeeting - a traves de su servicio se llevo a cabo el Webinar -, lo que impide que usuarios de Linux y OSX puedan ver el video.

Descargue el video, lo codifique de manera diferente y lo subi al sitio de Vimeo. Para los interesados aqui esta:

Desarrollando con Ruby on Rails from Mario A Chavez on Vimeo.

Para quienes están interesados en aprender Ruby On Rails, ya anuncie un segundo RailsCamp.

RailsCamp - Nivel 1

Después del RailsCamp de Enero, algunas personas me han preguntado si es posible realizar un curso para nivel 1, es decir enfocado a personas que apenas están entrando a conocer este entorno de desarrollo.

Pues bien, por este medio lanzo la convocatoria para los interesados al proximo RailsCamp, este sera de 15 horas -casi- continuas de entrenamiento en 3 dias:
Dia 1 -Viernes- de 6pm a 10pm
Dia 2 -Sábado- de 9am a 4pm
Dia 3 -Sábado- de 9am a 4pm

La fecha y el lugar aun están por definirse, ya que aun estoy buscando un espacio disponible para llevar a cabo el RailsCamp, donde puedan participar 10 personas.

  • Los objetivos del RailsCamp son:
  • Entender la arquitectura MVC
  • Manejo de dependencias con Bundler
  • Migraciones y modelos
  • Relaciones de datos a través de los modelos
  • Vistas, Helpers y Layouts
  • El controlador, CRUD y REST
  • El uso de Mailers

El proceso consiste en ir explicando estos conceptos al mismo tiempo de ir construyendo una aplicación en Ruby on Rails.

El costo tentativo del RailsCamp es de 1,500.00 pesos - este puede aun variar dependiendo del costo del lugar -, e incluye ademas del entrenamiento, cafeteria y comida.
NOTA: Si alguien necesita factura por el RailsCamp, el costo es diferente, por favor contactenme directamente a mario.chavez en decisionesinteligentes

Patrocinio para estudiantes: Al juntar a 10 personas para el RailsCamp, se le otorgara un patrocinio del 100% a un estudiante, asi que si eres estudiante dejame saber en los comentarios porque quieres aprender Ruby On Rails y al llenar el curso eligire al comentario mas convincente.

A los interesados, por favor les pido si pueden hacermelo saber en los comentarios del post.

Y ya para finalizar este post, también estoy preparando un MovilCamp, ya una vez que tenga los detalles los estaré publicando.

Servir aplicaciones Rack desde IIS en Windows

Por cuestiones de un proyecto en el que estoy trabajando, tuve la necesidad de crear una aplicación de Sinatra que se conectara a las bases de datos de un par de sistemas diferentes, a manera que la aplicación de Sinatra sea un API que exponga información que manejan esos sistemas de una manera unificada para ser consumida por otras aplicaciones/servicios.

Ambos sistemas tienen como base de datos a MSSQL Server, aunque uno esta escrito en ColdFusion y el otro en ASP.NET. Como unico requisito es que la aplicación de Sinatra sea servida por el Internet Information Server - IIS -; este requisito fue el inicio de una búsqueda de la mejor opción para hacerlo.

El motivo de usar Sinatra es simple, es muy sencillo hacer API para aplicaciones web con el DSL de Sinatra. Inicialmente trate de usar DataMapper para la conexión a MSSQL server, pero resulta que el conector tiene como dependencia una libreria en Java, motivo por el cual decidí usar ActiveRecord de Rails, ya que el driver para MSSQL esta implementado completamente en Ruby.

Mi primera opción para configurar IIS para servir solicitudes de Sinatra, fue usar Ruby y Fastcgi para IIS. Para esto me encontre con un post llamado “10 pasos para hacer que Ruby on Rails sea servidor con IIS y FastCGI”, el titulo se mostraba muy prometedor y el post bastante sencillo de seguir.

Pero, al final de cuentas no fue tan sencillo como seguir los 10 pasos, y al igual que muchos de los que publicaron comentarios en el post solo llegue hasta el mensaje de error:

FastCGI Handler Extension

Error 0x80004005 occurred processing request.

The FastCGI process exited unexpectedly

Y al igual que las otras personas, este error fue como toparse con pared, ya que no es descriptivo de lo que realmente causa el problema y al parecer nadie encontró una solución viable.

Después de darle vueltas e inclusive contemplar la posibilidad de reemplazar la aplicación de Sinatra por una aplicación de ASP.NET MVC - me negaba a hacerlo, ya que perderia la simplicidad y elegancia de Sinatra -, recordé que IronRuby tenia soporte para aplicaciones Rack en IIS.

Así que procedi a descargar a instalar IronRuby, así como el .NET 4.0, el cual es dependencia. Obviamente, y aunque con IronRuby logre mi cometido, el camino no fue simple.

Mi primer problema fue actualizar RubyGems con IronRuby, al tratar de ejecutar:

igem update —system

Fallaba con el error invalid exec_format “ir”, no %s
Aparentemente un bug que solo sucede con IronRuby, la manera de darle la vuelta es prevenir que el bug “truene” el proceso, atrapandolo y mostrando un mensaje del problema, pero permitiendo la continuación del proceso. La solución consiste en agregar un archivo con esta logica al código de RubyGems incluido en IronRuby, este post contiene los detalles de la solución.

Mi siguiente problema fue que ActiveRecord 3.0.3 no funciona con IronRuby 1.0.x, por lo que baje mi dependencia a ActiveRecord 2.3.10 y el problema se soluciono. Además de ActiveRecord, agregue como dependencia el ActiveRecord SqlServer Adapter, el cual configure para que se conecte a través de ADO.NET.

El siguiente paso fue hacerme del IronRuby.Rack.dll, el cual lo encontré en una gema del mismo nombre, la cual ademas contiene una serie de utilerias interesantes.

Por ejemplo en el folder de la aplicación de Sinatra ejecute:

rack2aspnet . sinatra

Esto creo un directorio bin, con las librerías necesarias de IronRuby y IronRuby.Rack, ademas de instalar Cassini, un servidor de Web basico para probar aplicaciones que son servidas a traves de ASP.NET. Tambien creo el archivo config.ru y web.config.

En este punto podemos probar nuestra aplicación con Cassini:

bin\cassini c:\wwwroot\miapp 9292 /

Pero al intentar conectarme a la URL http://localhost:9292, esta solo me muestra el siguiente error

C:/dev/ruby/lib/ruby/gems/1.8/gems/rack-1.2.1/lib/rack/utils.rb:138:in `union’: can’t convert Array into String (TypeError)

El problema es que IronRuby no funciona correctamente con rack-1.2.1, la solución es simple y esta descrita en este reporte de problema en Rack, hay que modificar la linea 138 de utils.rb, para que el lugar de ser:

Regexp.union(ESCAPE_HTML.keys)

sea

Regexp.union(ESCAPE_HTML.keys.join(‘,’))

Listo, mi aplicación de Sinatra es servida por Cassini.

La gema de IronRuby-Rack, provee de la herramienta deploy2iis, que permite crear y configurar una aplicación en IIS, desafortunadamente solo funciona con IIS7, en mi caso el servidor usa IIS6, por lo que procedi a crear la aplicación en el IIS de manera manual.

Hay algunas recomendaciones que debemos de tener en cuenta al crear y configurar nuestra aplicación en IIS6. Primero, si ya tenemos aplicaciones que estén corriendo en el IIS y que dependan del .NET < 4.x, hay que crear un nuevo pool, para permitir el tener aplicaciones con diferentes versiones de .NET, en el caso de IronRuby el framework 4.x es requerido. Una vez creado el nuevo pool, en la configuración de nuestra aplicación en IIS, le indicamos que use ese nuevo pool y también le indicamos que use .NET 4.x.

El siguiente punto es que necesitamos configurar la aplicación para que sea servida a través del filtro aspnet_isapi.dll e indicarle que no espere que los archivos a servir existam fisicamente en el sistema de archivos.

Esto es importante ya que nuestra aplicación, puede responder a diversas URLs, que generalmente no tienen extensión. Por ejemplo mi aplicación en Sinatra puede responder a las siguientes URLs

http://localhost/administration/models.xml

o

http://localhost/administration/models/88234.xml

Siendo que esos archivos no existen físicamente, son generados al momento de que se solicitan.

Adicionalmente tenemos que hacer un ajuste - si estamos en IIS6 -, en web.config, ya que este archivo hay que recordar que fue generado automáticamente por rack2aspnet. Por lo tanto este archivo esta generado para IIS7, el ajuste en sencillo, y solo consiste en corregir la manera en como se registra el “http handler” para IronRuby, en las siguientes lineas se muestra donde se tiene que hacer el registro para cada versión de IIS:

IIS7: configuration>system.webServer>handlers>add

IIS6: configuration>system.web>httpHandlers>add

Listo, en este punto ya podemos acceder a la dirección publica de nuestra aplicación de Sinatra, la cual será servida por IIS.

Definitivamente es una gran ventaja el poder usar IronRuby para ejecutar aplicaciones de Ruby en ambientes Windows, lado a lado con aplicaciones .NET. El único punto de desventaja es el tener que poner pequeños parches para permitir de la aplicaciones de Ruby funcionen correctamente en IronRuby, y el otro detalle es que no permita ejecutar librerías de Ruby más nuevas como en el caso de ActiveRecord.

Trabajando con Arel

ActiveRecord en Rails 3.0 sufrió un cambio significativo al cambiar la forma en como se generan las consultas de SQL. Y es que a partir de esta versión, ActiveRecord hace uso de ARel.

ARel es su definición oficial es la “Interpretación Orientada a Objetos de Algebra Relacional”, siendo la Algebra Relacional un modelo matemático para la representación de “queries” sobre datos.

Y si llegaron a este punto y leyeron palabras como “álgebra”, “matemático”; no, no paren de leer.

Algebra Relacional, suena como a algo “muy matemático”, ¿pero en términos de ActiveRecord que beneficios tenemos o en que se traduce?

Bueno hay 2 beneficios muy visibles del uso de ARel.

Primeramente ActiveRecord nos permite encadenar “queries”, lo que se traduce que programaticamente podemos crear consultas mas complejas, pero también nos ayuda a realizar una refactorizacion mas simple para eliminar duplicidad.

» Company.where(:code => ‘TST’).to_sql

=> “SELECT `companies`.* FROM `companies` WHERE (`companies`.`code` = ‘TST’) ORDER BY code desc”

» Company.where(:code => ‘TST’).where(:name => ‘Company’).to_sql

=> “SELECT `companies`.* FROM `companies` WHERE (`companies`.`code` = ‘TST’) AND (`companies`.`name` = ‘Company’) ORDER BY code desc”

» Company.where(:code => ‘TST’).order(:active).limit(20).to_sql

=> “SELECT `companies`.* FROM `companies` WHERE (`companies`.`code` = ‘TST’) ORDER BY code desc, active LIMIT 20”

ActiveRecord hace un buen trabajo creando una abstracción sobre ARel, con una interface simple para hacer consultas.

El segundo punto importante es que al momento de formar una consulta programaticamente ARel nos proporciona un objeto Query, el cual un no se ejecuta y que nos permite agregar mas “queries” a nuestra consulta en base a la información que nos proporciona el usuario.

» query = Company.where(:code => ‘TST’)

» query = query.order(:active)

» query = query.limit(20)

» query.to_sql

=> “SELECT `companies`.* FROM `companies` WHERE (`companies`.`code` = ‘TST’) ORDER BY code desc, active LIMIT 20”

Es decir podemos modificar nuestra consulta programaticamente antes de que sea enviada al servidor de base de datos para su ejecución.

A través del API de ActiveRecord podemos crear consultas de cierta complejidad, pero llega un momento en que la única forma de escribir nuestra consulta es usar código de SQL parcialmente, por ejemplo: No podemos escribir una consulta con OR únicamente usando el API de ActiveRecord.

» Company.where(‘code = ? or name = ?’, ‘TST’, ‘Company’).to_sql

=> “SELECT `companies`.* FROM `companies` WHERE (code = ‘TST’ or name = ‘Company’) ORDER BY code desc”

Podemos notar el 'code = ? or name = ?', 'TST', 'Company' que no se ve muy orientado a objetos. En las consultas mostradas previamente en este post hemos usado ARel de manera indirecta, ahora llega el momento de usarlo directamente para que nuestra consulta nuevamente se “sienta” mas orientada a objetos.

Lo primero que tenemos que hacer para utilizar ARel directamente es contar con la referencia de la tabla sobre la que vamos a ejecutar nuestra consulta, esto lo hacemos a través de nuestro modelo:

» company_table = Company.arel_table

Ahora podemos crear una consulta de la siguiente manera:

» company_table[:code].eq(‘TST’).to_sql

=> “`companies`.`code` = ‘TST’”

» Company.where(company_table[:code].eq(‘TST’)).order(‘code desc’).to_sql

=> “SELECT `companies`.* FROM `companies` WHERE (`companies`.`code` = ‘TST’) ORDER BY code desc”

Para lograr nuestra consulta con OR usando ARel en conjunto con ActiveRecord, simplemente tenemos que construir la parte del OR con ARel y dejar el resto a ActiveRecord.

» Company.where(company_table[:code].eq(‘TST’).or(company_table[:name].eq(‘Company’))).to_sql

=> “SELECT `companies`.* FROM `companies` WHERE ((`companies`.`code` = ‘TST’ OR `companies`.`name` = ‘Company’)) ORDER BY code desc”

Como podemos ver ARel es una buen avance sobre ActiveRecord en Rails para la realización de consultas, algo positivo es que aunque ActiveRecord nos presenta su API para consultas, no es posible acceder a ARel directamente.

Actualmente ARel es solo utilizado en ActiveRecord, por lo que tiene una conexión a este, pero en e sitio de ARel mencionan que dentro de los planes a futuro esta el romper esta relación, haciendo posible que ARel pueda utilizarse fuera de Rails y que el motor generador de las consultas trabaje con otros repositorios fuera de RBDMS, como puede ser XML o IMAP.