Solucionando el problema de Ruby y Rails en MacPorts

Ya antes había escrito en este mismo blog porqué MacPorts era la opción más conveniente disponible en OS X para instalar un entorno completo de desarrollo Ruby on Rails. Sin embargo, pronto descubriremos que los ports disponibles de los paquetes que usamos se actualizan frecuentemente mucho más rápido que nuestros propios proyectos. Esto es generalmente algo bueno, asegurándonos lo último y mejor del software de código abierto a sólo un comando o unos clicks de distancia.

Pero a veces, las versiones más recientes de paquetes importantes pueden "romper" la compatibilidad con el resto del stack de nuestra aplicación. Un triste caso es el conocido error de compatibilidad de Ruby 1.8.7, la versión actual de Ruby disponible en MacPorts, con versiones viejas de Rails (sobre todo las pre-2.0).

Con este problema me dí de bruces cuando al intentar actualizar el port de RubyGems para luego instalar la versión 2.2 de Rails con él, MacPorts también actualizó mi port de Ruby, una dependencia de RubyGems, inmediatamente dejando inusables a todas mis aplicaciones Rails 1.2.6 instaladas en mi MacBook.

Solucionar antes que desesperar

Después de investigar el problema, descubrí que la solución es crear un recurso local con la definición de la versión específica del port (Portfile) que deseamos y luego usar esa información para instalarla en lugar de la más reciente disponible con MacPorts.

En este artículo usaremos este método para instalar la última versión de Ruby 1.8.6 que estubo disponible en MacPorts (el "patchlevel 114") y su correspodiente versión de RubyGems en ese momento (v1.1.1), que luego actualizaremos a la actual v1.3.1 para permitirnos instalar la última versión de Rails y todas sus anteriores sin incovenientes.

(Todos los siguientes pasos los verifiqué exitosamente en Mac OS X 10.4 "Tiger" usando MacPorts 1.70, pero el proceso debería ser similar sino idéntico también en "Leopard").

Volver al futuro: Instalar Ruby 1.8.6 en lugar de 1.8.7

Primero creamos el directorio local /Users/Shared/dports para colocar allí los Portfiles con la información de las versiones específicas de los ports que queremos instalar, dándoles preponderancia sobre los disponibles en MacPorts.

$ mkdir /Users/Shared/dports

Obtenemos entonces la revisión del Portfile de Ruby correspondiente a su versión 1.8.6 "patchlevel-114" (el último antes de la versión 1.8.7) haciendo un checkout del repositorio de Subversion de MacPorts (para esto, obviamente, tenemos que tener el port de Subversion instalado y funcionando). La revisión correcta puede obtenerse de esta página.

$ cd /Users/Shared/dports
$ svn checkout -r 36429 http://svn.macports.org/repository/macports/trunk/dports/lang/ruby/ lang/ruby/

Actualizamos ahora nuestro índice de ports local:

$ portindex /Users/Shared/dports

Verificamos que la versión 1.8.6 está efectivamente agregada a la lista de las disponibles para RubyGems:

$ port list | grep lang/ruby
ruby                           @1.8.6-p114     lang/ruby
ruby                           @1.8.7-p72      lang/ruby

Ahora podemos desinstalar con confianza cualquier port de Ruby y RubyGems que tengamos (el orden siguiente es importante para no toparnos con errores de dependencias):

$ sudo port uninstall rb-rubygems ruby

Borramos "a mano" la documentación de RubyGems, versión 1.1.1 en este caso:

$ sudo rm -r /opt/local/lib/ruby/gems/1.8/doc/rubygems-1.1.1/

Instalamos la vieja y confiable versión 1.8.6 que acabamos de configurar localmente:

$ sudo port install ruby @1.8.6-p114

Y deberiamos ver algo como esto:

--->  Fetching ruby
--->  Verifying checksum(s) for ruby
--->  Extracting ruby
--->  Applying patches to ruby
--->  Configuring ruby
--->  Building ruby
--->  Staging ruby into destroot
--->  Installing ruby @1.8.6-p114_0+thread_hooks
--->  Activating ruby @1.8.6-p114_0+thread_hooks
--->  Cleaning ruby

Luego verificamos que efectivamente tenemos la versión deseada:

$ ruby -v
ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin8.10.1]

Instalar RubyGems 1.1.1 y actualizarla a la versión 1.3.1

Pero por supuesto, si intentamos instalar el port de RubyGems obtendremos un error diciendo que su versión actual 1.3.1 necesita por lo menos la versión 1.8.7 de Ruby:

$ sudo port install rb-rubygems
...
Command output: To use --vendor you need ruby >= 1.8.7, current 1.8.6.114

La solución es instalar la última versión de RubyGems en MacPorts que soportaba Ruby 1.8.6, su versión 1.1.1, y luego actualizarla a la 1.3.1 mediante el método "oficial" ofrecido por ella misma.

Entonces nos ubicamos nuevamente en el directorio /Users/Shared/dports y descargamos la revisión de Subversion del Portfile de RubyGems correspondiente a su versión 1.1.1, tal como podemos averiguarlo en esta página:

$ cd /Users/Shared/dports
$ svn co -r 35972 http://svn.macports.org/repository/macports/trunk/dports/ruby/rb-rubygems/ ruby/rb-rubygems/

Luego actualizamos nuevamente el índice de ports local:

$ portindex /Users/Shared/dports

Y verificamos que la versión 1.1.1 efectivamente está agregada a la lista de disponibles para RubyGems:

$ port list | grep rb-rubygems
rb-rubygems                    @1.1.1          ruby/rb-rubygems
rb-rubygems                    @1.3.1          ruby/rb-rubygems

Entonces instalamos la versión deseada de RubyGems con tranquilidad:

$ port install rb-rubygems @1.1.1

La instalación exitosa de RubyGems debería arrojar unos mensajes como estos:

--->  Activating autoconf @2.63_0
--->  Cleaning autoconf
--->  Fetching rb-rubygems
--->  Verifying checksum(s) for rb-rubygems
--->  Extracting rb-rubygems
--->  Configuring rb-rubygems
--->  Building rb-rubygems
--->  Staging rb-rubygems into destroot
--->  Installing rb-rubygems @1.1.1_0
--->  Activating rb-rubygems @1.1.1_0
--->  Cleaning rb-rubygems

Y para verificar que conseguimos la versión de RubyGems que queríamos podemos hacer:

$ gem -v
1.1.1

Ahora por fin actualizamos RubyGems 1.1.1 a su última versión 1.3.1 con la opción que incluye para ello, apartándonos bajo nuestro propio riesgo del port oficial disponible en MacPorts:

$ sudo gem install rubygems-update -v 1.1.1

Si todo sale bien, deberíamos ver algo como ésto (resumido para ahorrar espacio):

Updating RubyGems
Bulk updating Gem source index for: http://gems.rubyforge.org/
Updating rubygems-update
Successfully installed rubygems-update-1.3.1
Updating version of RubyGems to 1.3.1
Installing RubyGems 1.3.1

También podemos intentar con el siguiente comando, pero es mejor si sólo fue necesario el anterior:

$ sudo gem update --system

Y para verificar que la actualización se realizó correctamente:

$ gem -v
1.3.1

El Nirvana de Rails

En este punto podemos instalar las versiones más recientes de Rails, conservando las anteriores 1.x para los proyectos que lo necesiten, con la invaluable tranquilidad de que todas funcionarán como en el Nirvana:

$ sudo gem install rails -v 1.2.6
$ sudo gem install rails -v 2.0.5
$ sudo gem install rails -v 2.1.2
$ sudo gem install rails -v 2.2.2

Ubuntu salva el día en el servidor

Como ya lo había comentando antes en este mismo blog, mi distribución GNU/Linux de preferencia para montar un servidor donde hospedar mis aplicaciones Rails es la versión Server en su edición LTS (con soporte extendido) de Ubuntu, que en su última versión 8.04 incluye la versión 1.8.6.111 de Ruby que generosamente nos ahorrá todos los problemas anteriores.

Referencias

blog comments powered by Disqus

 

RSS Blog