No ha habido mucha actividad, en términos de grandes cambios o nuevas funcionalidades en el core de Rails. Así que lo mejor es dirigirse a los logs de los commits en busca de cambios menores o correcciones. Ha habido algunos avances en la refactorización y sorporte de threads en ActionPack, así como alguna actividad en ActiveModel, pero nada realmente concreto.

Soporte de thin en script/server

script/server ahora comprueba si Thin está instalado y lo utiliza. Esto es bastante cómodo si usamos Thin como nuestro servidor en producción y queremos usarlo también en desarrollo. Hay que añadir config.gem ‘thin’ al fichero environment.rb.

Este parche ha sido contribuido por uno de los chicos de fluxin, y estos son los cambios

Personalización de String#humanize mediante reglas de inflexión

La extensión String#humanize del core se utiliza para convertir cadenas con guiones bajos, por ejemplo nombres de tablas, en texto legible. Por ejemplo:

"actor_salary".humanize
=> "Actor salary" 
"anime_id".humanize
=> "Anime" 

Pero a veces esto no funciona tan bien, cuando tenemos tablas heredadas de otra aplicación o simplemente con nombres inhumanos como “act_sal_money” (que sería humanizada como “Act Sal Money”)

Ahora podemos especificar nuestras propias reglas de inflexión (igual que puede hacerse para personalizar las reglas de inflexión para plurales, singulares, etc.)

Inflector.inflections do |inflect|
  inflect.human /_cnt$/, '\1_count'
  inflect.human 'act_sal_money', 'Actor Salary'
end

Obsérvese que podemos usar expresiones regulares para convertir por ejemplo columnas como “click_cnt” en “Click Count”

Demos las gracias a Dan Manges y Pascal Ehlert por este cambio.

Condiciones sobre múltiples tablas utilizando hashes

Pratik ha entregado un pequeño (pero útil) cambio en ActiveRecord que permite especificar las condiciones de una tabla sobre la que se efectúa un JOIN en su propio hash. Por ejemplo:

Anime.all(
  :joins => :character,
  :conditions => {
    :active => true,
    :characters => { :gender => 'female' }
  }
)

La sentencia anterior encontrará todos los animes “activos” con personajes femeninos. Cambios

Aclaración: la columna semanal que publicaba Chu Yeow e su blog ha pasado al blog oficial de Ruby on Rails. Con este cambio la numeración de las entregas vuelve a empezar por el número 1.

Ha habido un buen puñado de cambios y mejoras de rendimiento en las últimas semanas desde la aparición de Rails 2.1, así que en lugar de volcarlas todas en un post enorme, serán repartidas en dos. En esta entrega hablaremos de las nuevas featuras y cambios en la API.

Cambios menores en la API

link_to ahora recibe un bloque

El helper link_to ahora recibe un bloque como argumento para aquellas ocasiones en las que tenemos textos muy largos con variable para nuestros enlaces


    <% link_to(@profile) do %>
      <strong><%= @profile.name %></strong> -
      <span>Status: <%= @profile.status %></span>
    <% end %>    

Es bastante más claro que


<%= link_to "<strong>#{@profile.name}</strong> " + 
"<span>Status: #{@profile.status}</span>", @profile %>

Los autores de este cambio son David Heinemeier y Sam Stephenson (de Prototype).

ActiveRecord::Base#merge_conditions es ahora parte de la API pública

Jeremy Kemper ha hecho público el método ActiveRecord::Base#merge_conditions.

Esto es bastante útil si en nuestras consultas a la base de datos tenemos condiciones de múltiples fuentes o querríamos, por alguna razón, combinar cualquier condición:


Post.merge_conditions(
      {:title => 'Lucky ☆ Star'},
      ['rating IN (?)', 1..5]
    )
=> "(`posts`.`title` = 'Lucky ☆ Star') AND (rating IN (1,2,3,4,5))" 

Debemos tener en cuenta que las uniones se hacen siempre con un AND lógico de SQL, nunca con un OR.

Detalles de este parche

Las asociaciones reciben una opción :validate

Las macros de las asociaciones ahora aceptan la opción :validate así:


class Anime > ActiveRecord::Base
  has_many :characters, :validate => true
end

Con esto le indicamos a ActiveRecord que valide las asociacion characters cuando almacene el modelo Anime, exactamente de la manera en que funciona :validates_associated. Por defecto el valor es falso, que es el funcionamiento por defecto de Rails 2.1 y anteriores, así que no es necesario perder la tranquilidad. Este mecanismo funciona también con el resto de macros (has_one, belongs_to, has_and_belongs_to_many)

Demos las gracias a Jan de Poorter y Pratik Naik por este cambio, que también resuelve un bug recalcitrante. Parche.

ActiveSupport::StringInquirer y los métodos de conveniencia Rails.env.development?

DHH ha añadido recientemente una subclase ActiveSupport::StringInquirer que permite hacer lo siguiente:


s = ActiveSupport::StringInquirer.new('awesome')
=> "awesome" 
s.awesome?
=> true
s.sucks?
=> false

Un uso inmediato de esto es cuando estamos comprobando el entorno en que se está ejecutando nuestra aplicación: Rails.env está recubierto por un StringInquirer, de forma que se pueden usar métodos de consuta como Rails.env.development? y Rails.env.production?

Detalles

Extensiones al core: Object#present? y Enumerable#many?

DHH también ha añadido algunas extensiones que, si bien son triviales, pueden contribuir a hacer nuestro código más legible. El primero es Object#present?, que equivale a !Object#blank?


[].present?
=> false
[1, 2].present?
=> true
"".present?
=> false
"heme aquí".present?
=> true

También se ha añadido una extensión Enumerable#many? que es simplemente un valor lógico que comprueba si enumerable.size > 1:


[].many?
=> false
[:solo_yo].many?
=> false
[:solo_yo, 'mi_amigo'].many?
=> true

Parche para Object#present? y parche para Enumerable#many?

Sintaxis declarativa de bloques para escribir tests

DHH debía de estar inspirándose en Jay Fields cuando escribió este terrón de azúcar sintáctico: ahora podemos escribir nuestros tests (Test::Unit) con forma de bloques declarativos:


test "Un anime debería ser no válido si cualquiera de sus personajes no es valido" do
  # Codigo normal de pruebas
end

Todos los stubs de tests generados por Rails utilizan ya esta nueva sintaxis.

Detalles del parche

Pruebas de rendimiento

Jeremy Kemper ha estado haciendo un gran trabajo en la optimización y mejora del rendimiento de Rails, así que no es de extrañar que haya introducido un nuevo tiempo de tests de integración: el test de rendimiento.

Ahora podemos usar el generador de tests de rendimiento (añadido por Pratik en el cambio 23232a) para generar un test de rendimiento que rellenar.


script/generate performance_test LoginStories

Para correr los tests de rendimiento es necesario tener instalado ruby-prof (>= 0.6.1), que aún no ha sido publicado pero se puede obtener la versión de desarrollo haciendo un checkout del código ei nstalando la gem uno mismo. (Es mejor utilizar el fork de Jeremy por el momento) Es interesante hacer notar que con la versión 0.6.1 ruby-prof soporta casos de pruebas escrtos usando Test::Unit.

A continuación basta con poner código de pruebas (pedir unas cuantas acciones de algún controlador – cualquier historia de usuario de la que queramos probar el rendimiento) y ejecutar el test. Obtendremos un resutlado como este (además de toda la salida habitual de ruby-prof en test/tmp/performance ):

> ruby performance/login_stories_test.rb 
Loaded suite performance/login_stories_test
Started
LoginStoriesTest#test_homepage (32 ms warmup)
        process_time: 11 ms
              memory: unsupported
             objects: unsupported
.
Finished in 0.870842 seconds.

Los resultados de memory y objects están no soportados porque aún no he parcheado mi intérprete de Ruby con el soporte para profiling de la memoria y el recolector de basura. Hay información de cómo hacerlo aquí. Dejaremos que lo explique gente más sabia.

Detalles del parche

(Este artículo es una traducción de Living on the edge of Rails (22), publicado por Chu Yeow en su blog redemption in a blog)

No ha habido cambios alucinantes en esta semana previa a la RailsConf -tal y como mencionó Gregg en el podcast de RailsEnvy estamos en la antesala de Rails 2.1 (probablemente será lanzado durante la misma RailsConf), así que es comprensible esta tranquilidad. Ah, y ahora todos los tests pasan con Ruby 1.9 después de que un recalcitrante error en module_eval haya sido corregido en el trunk de Ruby 1.9. (Véase este hilo para más información)

El informe de esta semana cubre los cambios efectuados en Rails entre el 19 y el 25 de Mayo de 2008.

Métodos first y last en asociaciones y ámbitos con nombre

¿Recordais cómo la integración de la gema has_finder nos permitía hacer cosas como Post.first y Post.last?

Ahora podemos ir un paso más allá y utilizar los mismo métodos en las asociaciones ActiveRecord. Por ejemplo:


post = Post.find(1)
first_comment = post.comments.first

Y si hemos definido un named scope llamado recent, podemos incluso hacer:


post.comments.recent.last

Esta pequeña mejora es cortesía de Ryan Bates (sí, el Ryan Bates de RailsCasts)

Métodos exist? y fragment_exist? para la caché

Los almacenes de caché en Rails (memcache, fichero, etc) ahora disponen de un método exist? que comprueba si la caché dispone de un valor guardado para una clave dada. Esto permite que los controladores Rails dispongan de un método fragment_exist? que nos permite preguntar si existe un fragmento de caché.


fragment_exist?('example.com/foo/bar')

El cambio correspondiente es http://github.com/rails/rails/commit/99860b72aebe0348f41e82d4710343498d89a84b#diff-2

Creación de registros en asociaciones con bloques como argumento

Ahora se pueden crear registros para asociaciones así


post.comments.create!(:title => 'Techcrunch') do |c|
     c.body = "Rails no escala!" 
end

Todo esto va parejo con el reciente cambio en ActiveRecord::Base.create del que ya hemos hablado por aquí

El autor de este parche es (otra vez) Ryan Bates

El cambio es este

¡Hasta la semana que viene!

(Este artículo es una traducción de Living on the edge of Rails (21), publicado por Chu Yeow en su blog redemption in a blog)

Esta ha sido otra semana tranquila (sólo ha habido dos cambios de importancia, en mi opnión) tras la liberación de la primera Release Candidate de Rails 2.1 Sigue el enlace donde están las instrucciones de instlaación -aunque si estás leyendo esta serie de posts probablemente no te importe (porque estas, ya sabes, viviendo en el filo) Bromas aparte, no te olvides de informar de cualquier fallo con el que te puedas topar cuando te actualices a 2.1 RC1 en el bug tracker de Rails – ¡es una versión candidata, así que cualquier informe de fallos será bien recibido!

El informe de esta semana cubre los cambios efectuados en Rails entre el 12 y el 18 de Mayo de 2008.

caches_action condicionales

caches_action ahora recibe una opción :if exactamente igual que caches_pages. Por ejemplo:


caches_action :index, :if => Proc.new { |c| !c.request.format.json? }

Esta pequeña mejora es obra de José Valim. El cambio relacionado está en http://github.com/rails/rails/commit/7708650f73ddb4db300ea2059c60c1d907a4384e

Fallo corregido: los finders de ActiveRecord siguen la opción select para garantizar que se incluyen las tablas necesarias en el SQL generado

La siguiente sentencia


Post.find(:all, :include => :author, :select => 'posts.*, authors.id as "author_id"', :limit => 2)

Generaría el código


SELECT posts.*, authors.id as "author_id" FROM "posts" LIMIT 2

Obsérvese que no se hace un JOIN sobre la tabla de autores. Este fallo ha sido corregido por John Devine, y el cambio correspondiente es http://github.com/rails/rails/commit/b28b54cab090bed8f099ef375b419a8f92390dd4

¡Hasta la semana que viene!

Este artículo es una traducción de Living on the edge of Rails (20), publicado por Chu Yeow en su blog redemption in a blog.

El informe de esta semana cubre los cambios entre el 5 y el 11 de Mayo de 2008 en Rails.

script/dbconsole

Se ha añadido un script en scripts/dbconsole que nos permite conectarnos a la base de datos usando el cliente de consola de la misma. Si por ejemplo necesitásemos conectarnos al servidor de base de datos de producción (¡más vale que sepamos lo que estamos haciendo!) podríamos ejecutar RAILS_ENV=production script/dbconsole y nos conectará a la base de datos utilizando el cliente de comandos de MySQL. También funcionará con las bases de datos SQLite y PostgreSQL.

Como siempre, para disponer de este script en las aplicaciones que ya tengamos funcionando debemos recordar ejecutar rake rails:update:scripts después de actualizarnos a la última versión edge de Rails

Esta pequeña mejora es obra de Steve Purcell, que ya tenía un plugin similar.

Los cambios correspondientes son http://github.com/rails/rails/commit/4a07103687084496b773e18a03b1f2f5e686f7ad

flash.now en tests

Esto era algo con lo que posiblemente muchos desarrolladores de Rails nos hemos topado a la hora de escribir tests de los mensajes flash que envía nuestra aplicación mediante flash.now. Básicamente: uno no puede hacer pruebas sobre los contenidos de flash.now porque siempre se vaciaban antes de que el código del test se ejecutase sobre ellos.

# En el controlador
flash.now[:notice] = 'Debes de estar de broma!'

# En el test
assert_equal 'Debes de estar de broma!', flash.now[:notice]
# FALLA porque flash.now es nulo

Andreas Neuhaus le echó un buen vistazo al funcionamiento y se aseguró de que se puedan hacer tests sobre flash.now sin tener que recurrir a assert_select

El cambio en cuestión está en http://github.com/rails/rails/commit/74eed6290e63111d1aad2b181692a84f4f040aea

No hay mucho más que reseñar pero, como siempre, si queremos conocer hasta los más minimos detalles, lo mejor es repasar los logs de commit de Rails.

Este artículo es una traducción de Living on the edge of Rails (19), publicado por Chu Yeow en su blog redemption in a blog.

Esta entrada cubre los cambios realizados en Rails entre el 29 de Abril y el 4 de Mayo de 2008.

change_table para las migraciones ActiveRecord

Gracias a Jeff Dean, que también ha escrito sobre la nueva funcionalidad podemos modificar una tabla con un bloque de la siguiente manera:


change_table :videos do |t|
  t.add_timestamps
  t.add_belongs_to :goat
  t.add_string :name, :email, :limit => 20
  t.remove_column :name, :email # puede recibir varios argumentos
  t.rename :new_name
  t.string :new_string_column # se ejecuta contra el nombre cambiado
end

Las funcionalidades clave son:
  • add_XX añadirá una nueva columna. Por ejemplo, add_string añadirá una nueva columna de tipo string
  • Por supuesto add_timestamps añadirá los cambios mágicos created_at y updated_at
  • remove_column puede recibir varios argumentos
  • rename renombraría la tabla

Una excelente mejora, de nuevo gracias a Jeff Dean. El grupo de cambios correspondiente a este parche es http://github.com/rails/rails/commit/96980bd561d79824b6cb6efbcbecdcbf8785d452

ActiveRecord::Base recibe un bloque, al igual que ActiveRecord::Base.new

En efecto, ahora podemos crear objectos ActiveRecord pasando un bloque como argumento exactamente igual que con ActiveRecord::Base.new:


@person = Person.create(params[:person]) do |p|
  p.name = 'Konata Izumi'
  p.age = 17
end

El autor es Adam Meehan, y el grupo de cambios correspondiente a este parche es http://github.com/rails/rails/commit/dd120ede53eaf71dee76894998a81626b7a689fc

Arreglo: change_column debería poder usar :null => true en un campo que anteriormente estaba marcado como false

Ahora podemos usar change_column en nuestras migraciones para alterar una columan como nulificable si anteriormente estaba marcada como NOT NULL

Esta corrección es cortesía de Nate Wiger y el grupo de cambios relacionado es http://github.com/rails/rails/commit/10ef65a3b054270ed3d458ec8eb7c2b9a3e638f7

Ahí va una rápida que me ha costado trabajo encontrar (gracias a kithpom en #rubyonrails): cuando tenemos varias versiones de la gema de Rails instaladas en nuestro sistema (por ejemplo, la 2.0.2 y la 1.2.6), si ejecutamos rails en la consola se creará un esqueleto de aplicación 2.0 ¿Qué pasa si, por desdicha, necesitamos crear una aplicación 1.2.x?

rails _1.2.6_ myapp

La explicación, en cat `which rails`

Ya están disponibles las transparencias de mi presentación en la II Conferencia Rails Hispana.

Lamentablemente, el grueso de la presentación consistió en una demo en la que, con mayor o menor fortuna, traté de mostrar parte de la funcionalidad que Slingshot nos ofrece con muy poco esfuerzo por nuestra parte. Esa parte os la teneis que imaginar :)

Actualización: también están disponibles en Slideshare:

Como ya ha anunciado Sergio, el próximo jueves comienza la II Conferencia Rails Hispana en Madrid. Este año, al igual que el anterior, estaré por allí y haré una presentación.

En este caso se trata de una introducción a Joyent Slingshot, la plataforma para integrar aplicaciones Rails en el escritorio. ¡Nos vemos allí!

Una de las críticas más habituales que se hace a Ruby es el pobre rendimiento del intérprete Ruby frente a otros lenguajes rivales. Las cifras indican que por lo general para un mismo algoritmo el intérprete de Ruby ofrece un menor rendimiento que Python, PHP, Perl, ponga su lenguaje favorito.

La respuesta comunmente aceptada para esta penalización de rendimiento suele ser que Matz es un gran diseñador de lenguajes pero su labor como implementador no es tan brillante. El intérprete de Ruby escrito por Matz, conocido como MRI (de Matz Reference Implementation, o Implementación de Referencia de Matz) adolece de no pocos problemas (hay quien afirma que un lenguaje como C no es buena elección a la hora de implementar lenguajes dinámicos)

En todo caso, la comunidad de Rubistas (con Matz a la cabeza) hace tiempo que ha asumido el problema de rendimiento en la MRI y han surgido no pocos proyectos para corregir esta deficiencia. Uno de los problemas con los que se enfrentan los valientes que desean implementar un lenguaje es que, a diferencia de esfuerzos recientes como Perl 6, el lenguaje Ruby no dispone de una especificación funcional. Por tanto, la única fuente fiable de documentación sobre los entresijos del lenguaje Ruby es el estudio del código fuente en C del intérprete escrito por Matz (de ahí el nombre MRI)

YARV

El primero de estos esfuerzos es, por derecho propio, YARV de Sasada Koichi, la reimplementación de Ruby usando su propia máquina virtual y un compilador a código de bytes. El trabajo de Sasada Koichi, basado en un enfoque más moderno que la implementación de Matz, es tan brillante que la versión oficial 1.9.1 de Ruby estará basada en YARV. Aquí hay una serie de gráficos que muestran las mejoras de rendimiento de YARV frente a la MRI. Como puede verse, aún hay algún trabajo por hacer pero cabe destacar que, por lo general, una aplicación Rails verá mejoras de rendimiento del 15% sólo por usar YARV.

Como se ha visto, YARV divide el problema de la implementación del lenguaje en dos etapas: un compilador de código de bytes y una máquina virtual que ejecuta dicho bytecode. Surge de manera natural la pregunta de si no sería posible usar alguna máquina virtual ya existente y generar bytecode compatible con ella. Y, hablando de máquinas virtuales, la de Java está más que probada.

Ruby en Java

De aquí surge JRuby, que consiste en escribir un intérprete Ruby escrito en Java. Inicialmente un proyecto con pocos visos de ver la luz, al cabo de año y medio -y probablemente gracias al apoyo de Sun- en la actualidad es posible (como ya hemos visto) ejecutar aplicaciones Rails dentro de un contenedor de aplicaciones Java, lo que da una idea de la madurez del proyecto. La versión para Ruby de Netbeans soporta JRuby por defecto. Una de las ventajas de ejecutar Ruby en una máquina virtual de Java, por supuesto, es tener acceso a código ya existente escrito en Java lo cual hace a JRuby la implementación ideal para integrar Rails en entornos enterprise. Otra ventaja es que JRuby por definición se verá beneficiado de las mejoras posteriores que se realicen en el intérprete Java.

Y si JRuby es un intérprete de Ruby escrito en Java, XRuby es un traductor de Ruby a bytecode de Java (o lo que es lo mismo, de un fichero .rb generará un .class) Este traductor está basado en ANTLR. Aun en sus etapas iniciales, XRuby ya es capaz de generar bytecode Java para toda la librería estándar de Ruby y para Ruby on Rails 1.2.x

Rubinius

El siguiente en la lista esRubinius. El enfoque de esta iniciativa consiste en escribir la mayor parte del lenguaje en Ruby y dejar que la máquina virtual -escrita en C- ejecute el menor subconjunto posible de funcionalidad. En concreto, Rubinius pone el énfasis en el recolector de memoria y la implementación de forks y threads. A destacar que Rubinius parece surgir del mundo Rails (Evan Phoenix trabaja en Engine Yard, proveedores de alojamiento avanzado Rails) por tanto buena parte de las mejoras que promete en el intérprete atacan a los problemas de rendimiento que más pueden aquejar a nuestras aplicaciones Rails.

Ruby sobre .NET

Por supuesto que si hablamos de implementar Ruby sobre máquinas virtuales ya existentes sería pecado olvidarse de Microsoft. Microsoft, ya sea de manera oficiosa u oficial, ha estado detrás de dos proyectos.

El primero es Ruby.NET. Se trata de un proyecto de código abierto impulsado por Wayne Kelly y John Cough de la Queensland University of Technology (en Australia) y parcialmente financiado por Microsoft. Sin embargo, según los propios autores, la tarea de soportar RoR aún no está lista para su lanzamiento público.

IronRuby es la segunda implementación de Ruby sobre .NET más interesante quizá porque surge de un desarrollador de Microsoft, John Lam. Lam se ha basado en el Dynamic Language Runtime , originalmente pensado para Python y LISP. Parece ser que el desarrollo de IronRuby ha sido lo suficientemente complejo como para justificar cambios en el propio DLR oficial de Microsoft para acomodar a Ruby.

Si bien los esfuerzos en .NET como vemos parecen estar más verdes que sus equivalentes en Java, conviene tener en cuenta -sobre todo si desarrollamos sobre Windows- a estos dos proyectos.

Conclusión

Es evidente que vivimos tiempos interesantes. Si a un lenguaje que, no olvidemos, ya es suficientemente rápido como para ser competitivo por derecho propio le añadimos las mejoras y optimizaciones que están ahora mismo en los laboratorios de los desarrolladores arriba mencionados sólo pueden venir buenas noticias.

¿Ruby sobre C? ¿Sobre Java? ¿ Sobre .NET? ¿Ruby sobre Ruby? ¡Elige tus armas!

Corriendo aplicaciones Rails en JBoss

El objetivo de esta anotación es mostrar los pasos necesarios para lanzar una aplicación Rails dentro de un servidor de aplicaciones Java, en este caso el popular JBoss La intención última es comprobar los progresos está llevando a cabo el equipo de JRuby. Quién nos lo iba a decir hace un año, así que… ¿quién nos dirá qué va a ocurrir para el año que viene?

Instalación de JRuby

El primer paso será la instalación de JRuby , por supuesto. Damos por ya instalado Java en nuestra máquina. Para Mac OS X, la instalación por defecto de Java será suficiente (lo cual es raro)

1
2
3
  cd ~/jrubydemo/
  wget http://dist.codehaus.org/jruby/jruby-bin-1.0.1.tar.gz
  tar zxvf jruby-bin-1.0.1.tar.gz

Y se creará el directorio jruby-1.0.1. A continuación, añadiremos las siguientes variables al entorno de ejecución actual, una forma de hacerlo es la siguiente

1
2
3
Tamarindo:~/jrubydemo/ juan$ cat > entorno
export JRUBY_HOME=`pwd`/jruby-1.0.1
export PATH=$JRUBY_HOME/bin:$PATH

Cada vez que cambiemos este fichero tendremos que acordarnos de ejecutar el nuevo entorno en todas las sesiones que tengamos abiertas, hasta que añadamos estas variables al entorno por defecto.


. entorno

Ya podemos comprobar que las variables de entorno están presentes. Posteriormente podremos añadir la carga de este entorno a nuestro profile, pero de momento nos bastará con recordar que hay que evaluar este archivo de entorno para poder trabajar con JRuby. Ya podemos hacer nuestra primera, emocionante prueba:

1
2
Tamarindo:~ juan$ jruby -v
ruby 1.8.5 (2007-08-23 rev 4201) [i386-jruby1.0.1]
1
2
Tamarindo:~ juan$ which gem
/Users/juan/jrubydemo/jruby-1.0.1/bin/gem

JRuby incluye su propia versión de gem, y todas las gemas que instalemos con el entorno de JRuby quedarán instaladas en $JRUBY_HOME/lib/gems, de manera que no romperemos nuestra instalación estándar de Rails y otra gemas.

Instalación de Rails sobre JRuby

Merced a la flexibilidad del sistema de paquetes de Ruby, este paso será muy sencillo. Para instalar a los sospechosos habituales bastará con:

1
2
gem install rails -y --no-rdoc
gem install activerecord-jdbc --no-rdoc --no-ri

Esto instalará las gemas habituales: ActionMailer, ActionPack, ActiveSupport, ActiveRecord, Rails, Rake, RSpec, etc. asi como el adaptador JDBC para ActiveRecord. En este punto es cuando cualquier tutorial de Rails que se precie creará una aplicación de prueba (por ejemplo, un blog, un CMS, un mashup o cualquier otra cosa) en menos de 5 minutos. Nosotros, que somos algo más vagos, optaremos por instalar una aplicación que ya tenemos lista en su repositorio de Subversion:

1
2
3
4
cd ~/jbossdemo
svn checkout  http://mi-repositorio.com/myapp/trunk myapp
cd myapp
jruby script/server

Y, si la base de datos está arrancada y ’’config/database.yml’’ está bien configurado, la aplicación funcionará sin más dilación. El mismo código de nuestra aplicación funcionará tanto sobre la implementación de Ruby en C que sobre la implementación en Java. No es poco.

Más difícil todavía: JBoss

Descargaremos JBoss de Sourceforge. El paquete zip es algo más pequeño:

1
2
3
4
http://labs.jboss.com/jbossas/downloads/   (4.2.1GA)
cd ~/jrubydemo/
wget http://downloads.sourceforge.net/jboss/jboss-4.2.1.GA.zip?modtime=1184616808&big_mirror=1
unzip jboss-4.2.1.GA.zip  (la versión zip es más pequeña)

Y por supuesto a nuestro fichero de entorno añadiremos:

1
2
3
4
cd ~/jbossdemo
export JRUBY_HOME=`pwd`/jruby-1.0.1
export JBOSS_HOME=`pwd`/jboss-4.2.1.GA
export PATH=$JRUBY_HOME/bin:$PATH

Configurando el acceso a bases de datos en JBoss

Este paso es lógicamente específico de JBoss, pero es necesario para correr nuestra aplicación. Dado que en el mundo Java no está aún muy extendido lo de la convención sobre configuración, tendremos que explayarnos un poco en el acceso a la base de datos, creando el fichero ’’jboss-4.2.1.GA/server/default/deploy/mysql-ds.xml’‘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
    <jndi-name>MySqlDS</jndi-name>
    <connection-url>jdbc:mysql://mysql-hostname:3306/myapp</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>usuario</user-name>
    <password>clave</password>
    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>

    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

Con esta configuración le hemos dicho a JBoss que acceda a MySQL usando JDBC para acceder a la base de datos. Pero aún necesitamos instalar el correspondiente driver JDBC para Java, lo que MySQL denomina conector . De esta página podremos descargar el conector en forma de archivo .zip y la instalación es tan sencilla como copiar un archivo ’’.jar’’ al directorio lib del directorio de nuestro servidor.

1
2
3
4
cd ~/jbossdemo
wget http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.3-rc.zip/from/http://mysql.rediris.es/
unzip mysql-connector-java-5.1.3-rc.zip
cp mysql-connector-java-5.1.3-rc/mysql-connector-java-5.1.3-rc-bin.jar  jboss-4.2.1.GA/server/default/lib/

Con todo esto, ya podremos probar si JBoss goza de buena salud.

cd $JBOSS_HOME
bin/run.sh

Tras varios mensajes esotéricos, JBoss cobra vida:

INFO  [Server] JBoss (MX MicroKernel) [4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA date=200707131605)] Started in 16s:863ms

También nos interesa el mensaje

[ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=MySqlDS' to JNDI name 'java:MySqlDS'

que indica que JBoss ha creado el gestor de conexiones MySQL. Es hora de mudar nuestra aplicación Rails.

Creando un archivo .war

La manera estándar de desplegar aplicaciones dentro de un contenedor Java es mediante el uso de archivos war” los cuales no son más que ficheros zip que contienen toda una jerarquía de directorios con clases y recursos estáticos (HTML, imágenes, etc) aderezados con ciertos metadatos. Cuando uno de estos ficheros aparece en el directorio adecuado del servidor, éste lo abre, analiza los metadatos y toma las acciones pertinentes para activar la aplicación.

Así, nos hace falta crear un fichero war que contenga nuestra aplicación Rails. Afortunadamente, no tenemos que preocuparnos mucho del asunto porque ya existe un plugin Rails que se encarga de ello, creado por Charles Nutter. Tenemos toda la información necesaria en este wiki

cd ~/jbossdemo/myapp
jruby script/plugin install svn://rubyforge.org/var/svn/jruby-extras/trunk/rails-integration/plugins/goldspike

Para configurar los contenidos de nuestro war no todo van a ser convenciones, tenemos que editar el archivo config/war.rb para referenciar el conector.

1
2
  
maven_library 'mysql', 'mysql-connector-java', '5.0.4'

Teniendo en cuenta que por defecto Goldspike ejecutará la aplicación Rails en modo producción, tendremos que configurar adecuadamente ’’config/database.yml’’ Por último:


rake war:standalone:create

Tras un rato de funcionamiento la tarea de Rake finalizará dejando un bonito myapp.war en nuestro directorio. Obsérvese que el fichero .war pesa la friolera de 18M: no en vano incluye todo JRuby, Rails y las gemas que tuviéramos instaladas. Si no hemos parado la anterior instancia de JBoss podemos copiar en caliente el war:

cp myapp.war /Users/juan/jbossdemo/jboss-4.2.1.GA/server/default/deploy/

Veremos que en JBoss comienzan a pasar cosas y nuestra aplicación cobra vida.

23:29:10,762 INFO  [TomcatDeployer] deploy, ctxPath=/myapp, warUrl=.../tmp/deploy/tmp22213myapp-exp.war/
23:29:11,322 INFO  [[/myapp]] Ruby is running in standalone mode
23:29:14,472 INFO  [[/myapp]] JRuby init time: 2082ms
23:29:26,946 INFO  [[/myapp]] Rails init time: 9818ms
23:29:26,947 INFO  [[/myapp]] Runtime 0 loaded
23:29:26,947 INFO  [[/myapp]] Requests can now be processed
23:29:35,874 INFO  [[/myapp]] Runtime 1 loaded

Básicamente, JBoss descomprime el war en un directorio temporal y lanza dos instancias de Rails, lo que sería equivalente a dos mongrels tradicionales (por supuesto todo esto en configurable, según se explca en el wiki de Headius)

Tras esto, y si no ha habido errores (es de suponer que no) ¡es el momento de probar nuestra aplicación! Sólo debemos tener en cuenta que la URL raíz es, por la configuración de JBoss por defecto, algo distinta: http://127.0.0.1:8080/myapp, por lo que las URLs absolutas de nuestra aplicación (si las hubiera, que no debería) dejarán de funcionar.

En este artículo haremos una breve introducción al servicio Amazon Elastic Computing Cloud (EC2) y describiremos los pasos necesarios para ejecutar nuestra propia instancia y lanzar una aplicación Rails.

Read the rest of this entry

Hace unos meses, los chicos de b-simple publicaron el tutorial en PDF RESTful Rails Development con licencia CC. Desde hoy, está disponible también la versión en castellano traducida por mí.

De la página del proyecto: NetworkFacade es una alternativa a DRb, XMLRPC, y REST, todo en uno.

Hay ejemplos de su uso como recubrimiento de sockets TCP, Unix y SSL, así como el acceso a las APIS REST de Flickr, Digg y Netvibes.

Mingle es una aplicación escrita con Ruby on Rails. Hasta aquí, nada de extrardinario.

Lo interesante llega cuando nos cuentan algunas de sus características: será una aplicación de escritorio para entornos corporativos y que deberá correr sobre Windows, Linux y Mac.

Y más interesante aún es la plataforma sobre la que corre esta aplicación Rails: usa como base de datos Derby y Jetty como servidor web. Nada que ver con los habituales mongrels y MySQL.

A estas alturas ya no nos sorprende saber que Mingle también se distribuirá como un fichero .war que se puede desplegar en cuaqluier contenedor J2EE.

Todo esto es posible gracias a JRuby