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í.
Enlace al artículo original en OnLamp (en inglés)
Bienvenidos de nuevo.
En la primera parte del tutorial apenas empezamos a vislumbrar todas las cosas que pueden hacerse con Ruby on Rails. Por ejemplo, no hablamos sobre la validación de datos, las transacciones en la base de datos, las callbacks, el subsistema de pruebas unitarias o la caché. No hicimos mención alguna de los helpers que ofrece Rails para hacernos la vida más fácil. Aunque en realidad es imposible hacer justicia a ninguno de estos temas en el espacio limitado de este artículo sí que trataremos con cierto detalle alguno de ellos y del resto presentaremos un breve resumen, con enlaces a páginas con información más detallada.
Tampoco entramos con profundidad en el lenguaje de programación Ruby (a propósito). Si te interesa leer un breve tratado sobre los porqués que hay detrás de Ruby y del código Rails que vimos en la primera parte, te recomiendo que visites el blog de Amy Hoy, concretamente la historia Really Getting Started in Rails.
Pero antes de pasar a cubrir todo este material, quiero completar los ejercicios de tareas que dejamos pendientes al final de la primera parte:
- Ya no hay forma de eliminar una receta. Añádele un botón -o enlace- de borrado a la plantilla de edición.
- En la página principal de las recetas no hay ningún enlace a las páginas que permiten editar categorías. Arréglalo.
- Estaría bien poder visualizar de alguna forma sólo las recetas que pertenecen a una categoría particular. Por ejemplo, tal vez me gustaría ver una lista de todas los snacks o una lista de todas las bebidas. En la página que lista las recetas, haz que el nombre de la categoría sea un enlace a una página que visualice todas las recetas de esa categoría.
Un astuto lector nos ha señalado que después de añadir categorías a nuestra
aplicación ya no era posible crear nuevas recetas porque la acción new
del controlador Receta, tal y como la proporciona el andamiaje no tiene
manera de asignar una categoría, y esto hace que la acción list en
la lista de recetas provoque un error. Por supuesto esto hay que arreglarlo.
¿Estás listo? ¡Empezamos!
Actualización de Ruby on Rails
[N. del T: aunque las versiones de Rails y de los componentes que has instalado si has seguido los pasos de este artículo son superiores a las que describe Curt y por tanto no es necesario actualizarse (o al menos no tan perentorio), el procedimiento que él describe para actualizar nuestro paquete Rails sí que sigue siendo válido, asi que también lo incluiré en la versión traducida.]
Cuando escribí la primera parte, la última versión de Rails era la 0.9.3, mientras que en el momento de escribir esta segunda parte, Rails ya va por la versión 0.10.0 y tiene algunas caracerísticas nuevas. Utilizaremos Rails 0.10.0 en este artículo, así que describiremos la actualización. Ten en cuenta que si te instalaste Rails después del 24 de Febrero de 2005 ya tienes la 0.10.0 instalada.
La figura 1 muestra cómo ver qué Gems de Ruby tenemos instaladas, así como sus números de versión. Como en la primera parte, estoy trabajando en un sistema Windows, así que tendrás que traducir un poco todo esto si usas una plataforma diferente.

Figura 1. Listado de Gems instaladas
Abre una ventana de terminal y ejecuta lo siguiente:
gem list --local
Truco: el comando gem list --remote mostrará todas las gems
disponibles en el servidor de rubyforge.org.
Si no tienes instalado Rails 0.10.0 (o posterior), para actualizar a la última versión sólo hace falta volver a ejecutar el comando:
gem install rails
Actualización de seguridad de MySQL
En la primera parte, te recomendé que dejases la clave de administrador de MySQL vacía porque (en el momento de escribir el artículo) Rails aún no soportaba el nuevo protocolo de claves. Muchos de vosotros no estabais conformes con esta situación y, para empeorarlo todo, ahora existe un virus que explota vulnerabilidades de clave en MySQL sobre Windows. Afortunadamente, a partir de la versión 0.9.4, Rails soporta el nuevo protocolo de claves.
Nueva funcionalidad del scaffold
Rails ha incoporado una nueva funcionalidad en el andamiaje, que no exploraremos aquí en profundidad pero que es tan interesante que no quiero dejar pasar la oportunidad de contarla. Es mejor ilustrarla con un ejemplo.
En la primera parte se vio como crear un modelo y un controlador para la clase
Receta con los siguientes comandos:
ruby script\generate model Receta
ruby script\generate controller Receta
Y luego instanciamos el andamiaje insertando scaffold
:receta en la clase RecetaController. Todo lo generado
por este sistema, es decir, el controlador con métodos
CRUD (creación, acceso, actualización y borrado) así como las plantillas
resultantes, eran creados al vuelo en tiempo de ejecución y no era posible
inspeccionarlos.
Esta técnica sigue funcionando, pero ahora tenemos otra opción. Podemos ejecutar el siguiente comando,
ruby script\generate scaffold Receta
que generará tanto el modelo como el controlador y además crea el código y vistas del andamiaje para todas las operaciones CRUD, lo cual nos permite ver este código generado y modificarlo para adaptarlo a nuestras necesidades. Conviene tener cuidado porque si ya se han creado modelos, controladores o plantillas sobreescribirá cualquier fichero existente al ir generando los contenidos.
Acabar la aplicación Recetario
Ha llegado la hora de pulir un poco la aplicación de la lista de recetas. Después presentaré otras prestaciones de rails que estoy seguro que resultarán interesantes.
Recuerda: en la primera parte, creamos la aplicación del recetario en el directorio c:\rails\recetario; y todas las rutas de directorio que se usan en este artículo asumirán este directorio base. Si escoges un lugar distinto asegúrate de hacer los cambios apropiados en los ejemplos de este artículo.
También te puedes descargar el codigo fuente de la versión en inglés de este tutorial en un único archivo zip. Funcionará bajo Rails 0.13 y posteriores, así que si aún utilizas una versión anterior de Rails, te sugiero que sigas las insrucciones de actualización descritas anteriormente.
Ah, y para todos los que estáis haciendo trampas (ellos saben quiénes son)
y teneis pensado descargar el código fuente sin pasar primero por la primera
parte, también os hará falta crearos una base de datos llamada
recetario en MySQL y rellenarla.
Creación de una nueva receta con categorías
Dado que el código sigue usando el andamiaje para crear nuevas recetas, no hay manera de asignar una categoría a una receta. Esto no sería tan grave salvo por el detalle de que la página que hemos creado para mostrar todas las recetas asume que cada receta tendrá asignada una categoría y Rails generará un error si esto no se cumple. Esto significa que, en el estado que dejamos las cosas en la primera parte, tras añadir una nueva receta tendremos un error al intentar ver la lista de recetas.
El arreglo consiste en capturar la acción new del andamiaje como
hicimos con la acción edit. Abre
c:\rails\recetario\app\controllers\receta_controller.rb y añade el método
new como en la figura 2.

Figura 2. El nuevo código del método new
del controlador Receta.
La sentencia @receta = Receta.new crea un nuevo objeto receta vacío y se lo
asigna a la variable de instacia @receta. Recuerda que una instancia
de la clase Receta representa una fila en la tabla recetas de nuestra
base de datos. Así pues cuando creamos una nueva instancia, la clase Receta puede
asignar valores por defecto para que los utilice la plantilla de la
vista.
Ahora mismo la clase del modelo Receta no pone ningún valor por defecto, pero
la plantilla que voy a mostrar usará cualquier cosa que esté
en el objeto @receta para inicializar el formulario del display. Más
adelante, puedes añadir los valores por defecto en la clase Receta que se mostrarán
cuando crees una nueva receta.
Como con la acción edit, este código también recupera una colección
de todas las categorías de forma que pueda visualizar una lista desplegable
con las categorías de entre las cuales el usuario puede escoger. La variable
de instancia @categorias es la que lleva esta lista.
En el directorio c:\rails\recetario\app\views\receta, crea un fichero
denominado new.rhtml que contenga la plantilla que se muestra
debajo. Como es habitual, se trata en su mayor parte de HTML con algo de
código para mostrar las etiquetas select y
option para el desplegable con la lista de categorías:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<head>
<title>Nueva Receta</title>
</head>
<body>
<h1>Nueva Receta</h1>
<form action="/receta/create" method="post">
<p>
<b>Titulo</b><br/>
<input id="receta_titulo" name="receta[titulo]" size="30" type="text" value=""/>
</p>
<p>
<b>Descripcion</b><br/>
<input id="receta_descripcion" name="receta[descripcion]" size="30" type="text" value=""/>
</p>
<p>
<b>Categoria:</b><br/>
<select name="receta[categoria_id]">
<% @categorias.each do |categoria| %>
<option value="<%= categoria.id %>">
<%= categoria.nombre %>
</option>
<% end %>
</select>
</p>
<p>
<b>Instrucciones</b><br/>
<textarea cols="40" id="receta_instrucciones" name="receta[instrucciones]"
rows="20" wrap="virtual">
</textarea>
</p>
<input type="submit" value="Create"/>
</form>
<a href="/receta/list">Back</a>
</body>
</html> |
Como puede verse no hay mucha diferencia con respecto a la plantilla del
método edit que ya vimos en la primera parte. Hemos omitido
la fecha de la receta porque la ajustaremos por código cuando el usuario
envíe el formulario a la aplicación, para estar seguros de que la fecha de
la receta siempre será su fecha exacta de creación.
Si observas la etiqueta del formulario verás que se envía a la acción
create del controlador receta. Edita
c:\rails\recetario\app\controllers\receta_controller.rb y añade
el método create, que recibirá los datos introducidos en el
formulario anterior:
1 2 3 4 5 6 7 8 9 |
def create @receta = Receta.new(@params['receta']) @receta.fecha = Date.today if @receta.save redirect_to :action => 'list' else render_action 'new' end end |
Este método en primer lugar crea un nuevo objeto para la receta y lo
inicializa con los parámetros introducidos en new.rhtml.
Luego le ajusta la fecha a la receta con la fecha de hoy y le indica al objeto
receta que se guarde en la base de datos. Si la operación tiene
éxito, nos redirige a la acción listado que muestra todas las recetas, mientras
que si no hemos podido grabar los datos en la base de datos, volveremos a
la acción new de forma que el usuario lo pueda volver a intentar.
Vamos a probarlo. Arranca el servidor web abriendo una ventana de terminal, cambiando
al directorio c:\rails\recetario y ejecutando el comando
ruby script\server. Luego abre con el navegador
http://127.0.0.1:3000/receta/new
y añade una nueva receta como en la figura 3.

Figura 3. Nueva receta con categoria
Tras crear la nueva receta debería verse algo parecido a la figura 4.

Figura 4. Listado con todas las recetas
Borrado de recetas
Si recuerdas la primera parte del artículo, una vez que escribimos nuestra propia acción para el listado de recetas (sustituyendo la del scaffold) dejamos de poder borrar una receta. Para implementar esto en la acción del listado, añadiré un enlace para el borrado después del nombre de cada receta en la página principal, de forma que al seguir ese enlace se borre su receta asociada. Esto es fácil.
Primero, edita c:\rails\recetario\app\views\receta\list.rhtml y añadele el enlace al borrado de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<head>
<title>Todas las Recetas</title>
</head>
<body>
<h1>Recetario Online - Todas las Recetas</h1>
<table border="1">
<tr>
<td width="40%"><p align="center"><i><b>Receta</b></i></td>
<td width="20%"><p align="center"><i><b>Categoria</b></i></td>
<td width="20%"><p align="center"><i><b>Fecha</b></i></td>
</tr>
<% @recetas.each do |receta| %>
<tr>
<td>
<%= link_to receta.titulo,
:action => "show",
:id => receta.id %>
<font size=-1>
<%= link_to "(delete)",
{:action => "delete", :id => receta.id},
:confirm => "¿Seguro que quieres borrar #{receta.titulo}?" %>
</font>
</td>
<td><%= receta.categoria.nombre %></td>
<td><%= receta.fecha %></td>
</tr>
<% end %>
</table>
<p><%= link_to "Nueva receta", :action => "new" %></p>
</body> |
El cambio principal es que hemos añadido este enlace:
1 2 |
<%= link_to "(delete)", {:action => "delete", :id => receta.id}, :confirm => "¿Seguro que quieres borrar #{receta.titulo}?" %> |
Este enlace es un poco distinto a los que hemos venido añadiendo hasta ahora, porque emplea una opción que genera automáticamente un diálogo de confirmación Javascript. Si el usuario pulsa en OK en este diálogo se seguirá el enlace, y si pulsa en Cancelar no se ejecutará ninguna acción.
Probémoslo visitando esta URL
http://127.0.0.1:3000/receta/list
Intenta borrar la receta llamada "Agua helada", pero pulsa Cancelar cuando aparezca
el diálogo. Deberías ver algo parecido a la figura 5.

Figura 5. Diálogo de confirmación al borrar una receta
Vuelve a intentarlo, pero esta vez confirma el diálogo. ¿Ha aparecido lo que muestra la figura 6?

Figura 6. Error al borrar la receta del agua helada
Está bien, lo admito: lo he hecho a propósito para recordar que no pasa nada
si se cometen errores. He añadido un enlace a la acción delete en la plantilla
de la vista, pero ¡no hemos creado dicha acción en el controlador!
Edita c:\rails\recetario\app\controllers\receta_controller.rb y añade
el siguiente método delete:
def delete
Receta.find(@params['id']).destroy
redirect_to :action => 'list'
end
La primera línea encuentra la receta con el ID recibido en el enlace, y luego invoca
el método destroy de la receta. La segunda línea nos redirige a la acción
de listado.
Vamos a intentarlo otra vez. Abre
http://127.0.0.1:3000/receta/list
e intenta borrar la receta de Agua helada. Esta vez debería aparecer
la figura 7, sin la receta de Agua Helada.

Figure 7. Hemos borrado la receta de agua helada
Utilizando los layouts
En la primera parte utilizamos el andamiaje para proporcionar todas las operaciones CRUD para las categorias, pero no creé ningún enlace desde nuestra página principal del listado de recetas. En vez de colocar un enlace en la página del listado de recetas, quiero hacer algo que por lo general me será más util: crear un número de enlaces que aparecerán debajo de todas mis páginas. Rails tiene una característica, los layouts, que han sido especialmente concebidos para esta tareas.
Casi todos los sitios web muestran cabeceras y pies de página comunes. Esto se consigue haciendo que cada página "incluya" un texto especial para la cabecera y el pie de página. Los layouts de Rails le dan la vuelta a este patrón haciendo que el fichero del layout "incluya" el contenido de la página. Es más fácil verlo que describirlo.
Edita c:\rails\recetario\app\controllers\receta_controller.rb y
añade la linea layout inmediatamente después de la definición
de la clase, como se muestra en la figura 8.

Figura 8. Añadiendo un layout al controlador de Receta
Con esto le decimos al controlador de las recetas que utilice el archivo
standard-layout.rhtml para la maquetación de todas las páginas que tenga que pintar, y Rails lo buscará en c:\rails\recetario\app\views\layouts\standard-layout.rhtml. Crea el archivo con el siguiente contenido:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<head>
<title>Recetario Online</title>
</head>
<body>
<h1>Recetario Online</h1>
<%= @content_for_layout %>
<p>
<%= link_to "Crear nueva receta",
:controller => "receta",
:action => "new" %>
<%= link_to "Ver todas las recetas",
:controller => "receta",
:action => "list" %>
<%= link_to "Ver todas las categorías",
:controller => "categoria",
:action => "list" %>
</p>
</body> |
Sólo hay una diferencia con respecto a las otras plantillas que hemos creado hasta ahora, se trata de la siguiente línea:
<%= @content_for_layout %>
Aquí es donde se insertará el contenido pintado por cada acción del controlador en la plantilla del layout. Observa también que he usado enlaces que especifican tanto el controlador como la acción (hasta ahora, por defecto iban al mismo controlador que se estaba ejecutando) Aunque esto es obligatorio en el caso del enlace al listado de categorías, en el caso de los otros dos se podría haber usado la forma abreviada (sólo la acción).
Pero antes de probarlo, hace falta hacer una cosa más. Las plantillas anteriores para las recetas tenían algunas etiquetas HTML que ahora aparecen en el layout, por lo tanto editaremos c:\rails\recetario\app\views\receta\list.rhtml y borraremos las lineas del princpio y del final para que quede así:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<tr>
<td width="40%"><p align="center"><i><b>Receta</b></i></td>
<td width="20%"><p align="center"><i><b>Categoria</b></i></td>
<td width="20%"><p align="center"><i><b>Fecha</b></i></td>
</tr>
<% @recetas.each do |receta| %>
<tr>
<td>
<%= link_to receta.titulo,
:action => "show",
:id => receta.id %>
<font size=-1>
<%= link_to "(borrar)",
{:action => "delete", :id => recipe.id},
:confirm => "¿Seguro que quieres borrar #{recipe.titulo}?" %>
</font>
</td>
<td><%= receta.categoria.nombre %></td>
<td><%= receta.fecha %></td>
</tr>
<% end %> |
Igualmente, edita c:\rails\recetario\app\views\receta\edit.rhtml y c:\rails\recetario\app\views\receta\new.rhtml para quitar las mismas líneas. Recuerda que sólo deben quedar las etiquetas del formulario y lo que queda entre ellas.
Abre http://127.0.0.1:3000/receta/list, y deberías ver algo parecido a la figura 9.

Figura 9. Utilizando un layout con enlaces comunes
Los tres enlaces que aparecen abajo, al final de la página, deberían salir en todas las páginas generadas por el controlador de las recetas. ¡Compruébalo!
Si pulsas en el enlace de «Ver todas las categorías», te darás cuenta de que los nuevos enlaces no salen. Esto se debe a que el listado de categorías es generado por el controlador de las categorías, y el único controlador que sabe usar el nuevo layout es el de las recetas.
Para corregirlo, edita c:\rails\recetario\app\controllers\categoria_controller.rb y añade, igual que antes, la linea de
layout como en la figura 10.

Figura 10. Añadiendo el layout al controlador de las categorías
Ahora deberían verse los enlaces comunes en la parte inferior de todas las páginas mostradas por la aplicación del recetario.
Mostrar las recetas de una categoría específica
La última tarea que nos queda es añadir la posibilidad de mostrar en nuestro listado sólo las recetas que pertenezcan a una categoría en particular. Cogeremos la categoría visualizada con cada receta en la página principal y la convertiremos en un enlace que mostrará sólo las recetas de esa categoría.
Para hacerlo, cambiaremos la plantilla de la lista de recetas para aceptar un parámetro en la URL que especificará por qué categoría realizar el filtrado, o bien ver todas las categorías si el usuario ha omitido el parámetro. Por tanto, en primer lugar tengo que cambiar el método de la acción list para usar este parámetro y pasárselo a la plantilla de la vista.
Edita c:\rails\recetario\app\controllers\receta_controller.rb y modifica
el método list así:
def list
@categoria = @params['categoria']
@recetas = Receta.find_all
end
Y luego edita c:\rails\recetario\app\views\receta\list.rhtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<tr>
<td width="40%"><p align="center"><i><b>Receta</b></i></td>
<td width="20%"><p align="center"><i><b>Categoria</b></i></td>
<td width="20%"><p align="center"><i><b>Fecha</b></i></td>
</tr>
<% @recetas.each do |receta| %>
<% if (@categoria == nil) || (@categoria == receta.categoria.nombre)%>
<tr>
<td>
<%= link_to receta.titulo,
:action => "show",
:id => receta.id %>
<font size=-1>
<%= link_to "(borrar)",
{:action => "delete", :id => receta.id},
:confirm => "¿Seguro que quieres borrar #{receta.titulo}?" %>
</font>
</td>
<td>
<%= link_to receta.categoria.nombre,
:action => "list",
:categoria => "#{receta.categoria.nombre}" %>
</td>
<td><%= receta.fecha %></td>
</tr>
<% end %>
<% end %> |
Hay dos cambios fundamentales. Primero, la línea:
<% if (@categoria == nil) || (@categoria == receta.categoria.nombre)%>
decide si tenemos que mostrar la receta que se está tratando en el bucle. Si la categoría es nil (es decir, no había parámetro de categoría en la URL), o si la categoría del parámetro recibido en la URL coincide con la categoría de la receta actual, se muestra.
En segundo lugar, esta línea:
1 2 3 |
<%= link_to receta.categoria.nombre,
:action => "list",
:categoria => "#{receta.categoria.nombre}" %> |
crea un enlace a la acción de listado que incluya el parámetro de categoría apropiado.
Abre http://127.0.0.1:3000/receta/list y pulsa en uno de los enlaces de snacks. Debería tener el aspecto de la Figura 11.

Figure 11. Listado sólo de snacks
¿Ya? ¿Cuánto hemos tardado?
¡Ya está! Tenemos una aplicación online razonablemente funcional desarrollada en un tiempo record. Por supuesto, es un esqueleto que está pidiendo a gritos un mejor acabado.
Entre tantas palabras y pantallas puede que se haya difuminado (al menos un poco) qué es lo que este código puede hacer y en qué cantidad de tiempo de desarrollo. Con vuestro permiso, voy a presentaros algunas estadísticas para ponerlo todo en perspectiva.
Por suerte, Rails tiene ciertas facilidades que nos ayudan a respondernos estas preguntas. Abre una ventana de terminal en el directorio de la aplicación (c:\rails\recetario) y ejecuta el comando:
rake stats
Deberían salir unos resultados parecidos a los de la figura 12 (LOC significa "líneas de código")

Figura 12. Estadísticas de desarrollo
No veremos una descripción detallada de cada cifra que aparece en el listado, sin embargo la última línea tiene lo que quiero destacar:
Code LOC: 47
Esto significa que el número real de líneas de código de esta aplicación (sin contar comentarios o el código de pruebas) es 47. ¡He tardado una media hora en crear la aplicación! No es posible alcanzar este grado de productividad en ningún otro entorno de desarrollo de aplicaciones web que yo conozca.
A lo mejor piensas que esta es una experiencia aislada que usa un ejemplo simple (trivial si se quiere), o quizá piensas que esto puede servir para proyectitos pequeños, pero que no puede escalarse a soluciones más grandes. Si albergas estas dudas, la próxima sección puede ayudar a aclararlas.
Historias de éxito con Ruby on Rails
Rails es un framework relativamente joven: en el momento de escribir este artículo tan sólo han pasado unos seis meses desde la primera versión pública. Sin embargo, Rails ha debutado con tanta estabilidad y características que rápidamente ha surgido una prometedora comunidad a su alrededor. En este lapso de tiempo han aparecido varias aplicaciones web desarrolladas usando Ruby on Rails.
Basecamp
De la web del propio sitio:
Basecamp es una herramienta basada en web que te permite gestionar proyectos (o simplemente ideas ) y crear de forma rápida extranets para clientes o proyectos. Te permite a tí y a tus clientes (o a tu eqipo de desarrollo) mantener las conversaciones, ideas, planificaciones, listas de tareas y más en una localización central protegida por claves.
Basecamp fue la primera web comercial que funcionaba con Ruby on Rails, y fue desarrollada por David Heinemeier Hansson, el creador de Rails. En el momento de su inauguración, contenía 4000 líneas de código con dos meses de desarrollo por un único programador. A finales de 2004, Basecamp declaró que había superado la marca de 10000 usuarios registrados. El número de usuarios real se considera información privada, pero la página principal afirma que los usuarios se cuentan por "decenas de miles".
43 Things
43 Things es una aplicación social para fijar objetivos. En la actualidad tiene 6000 usuarios registrados y cientos de miles de visitas anónimas. 43 Things consiste en 4500 líneas de código escritas en tres meses por tres desarrolladores trabajando a tiempo completo.
Ta-da Lists
Ta-da Lists es un servicio
gratuito que permite gestionar listas compartidas de tareas pendientes. Su
interfaz de usuario es muy ágil, y utiliza XMLHttpRequest para
minimizar las esperas al servidor. Esta aplicación la hizo un desarrollador
en una semana, produciendo 579 líneas de código.
Snow Devil
Snow Devil es una tienda online especializada en snowboards y equipamiento relacionado. Ha sido recientemente inaugurada, por lo que no disponemos de información de uso en este momento. Sin embargo, sí que sabemos que la aplicación tiene 6000 líneas de código escritas por dos desarrolladores en cuatro meses.
Rediseño de CD Baby
CD Baby es una popular tienda de música independiente. Abierta en 1998, tiene en catálogo 82443 artistas que han vendido entre todos 1.2 millones de CDs, generandoles unos ingresos de 12 millones de dólares a dichos artistas.
La anterior página web de CD Baby consistía en 90000 líneas de código PHP que cada vez se hacían más difíciles de manejar. Sus autores están en proceso de reescribirlo todo con Ruby on Rails. Aún es pronto para encontrar información acerca del desarrollo pero el propietario de CD baby publica en un blog el proceso y el avance de la conversión.
¿Qué quiere decir todo esto?
En última instancia, tener un buen diseño siempre influye más que el framework en el rendimiento de tu aplicación: hay que pensar detenidamente el diseño de la base de datos y los índices de las tablas, analizar los patrones de acceso y plantearse desnormalizar los datos, buscar oportunidades para cachear datos preprocesados...
Rails tiene características muy potentes que hacen fácil prototipar y desarrollar tu aplicación más deprisa, lo cual te dejará más tiempo para pensar acerca de las prestaciones de tu aplicación y cómo afinar su rendimiento.
Un repaso breve a las características de Ruby on Rails
Hay muchas funcionalidades de Rails de las que no hemos hablado en este artículo. Me gustaría mencionar algunas de ellas (con enlaces a información adicional) para terminar de redondear la impresión general de las herramientas que ofrece Rails.
Caché
Mantener una caché es una forma barata de acelerar la aplicación guardando los resultados de procesamientos previos (cálculos, llamadas a la base de datos, visualizaciones de página, etc.) de forma que para la siguiente vez se omita el procesamiento. Rails proporciona tres niveles de caché, con diversos grados de granularidad:
- caché de páginas
- caché de acciones
- caché de fragmentos
Validación y callbacks
Debes validar los datos para estar seguro de que son correctos y
completos antes de escribirlos en la base de datos.
Rails dispone de un mecanismo simple que permite a tu aplicación validar
un objeto de datos antes de que el propio objeto actualice o cree
los campos correspondientes en la base de datos. Léete el
Validation
How-to o ve directamente a la
documentación del API sobre validación.
Las callbacks de ActiveRecord se "enganchan" a un objeto de datos y pueden activar cierto código que se ejecutará antes o después de que una operación altere el estado del objeto.
Transacciones
ActiveRecord también soporta transacciones. Citando directamente la documentación:
Las transacciones son bloques protegidos donde las sentencias SQL sólo son permanentes si todas tienen éxito como una única acción atómica. El ejemplo clásico es el de una transferencia entre dos cuentas donde sólo se puede hacer un depósito en la cuenta destino si la cuenta de origen dispone de fondos. Las transacciones fuerzan la integridad de la base de datos y protegen los datos de errores en el código del programa o caídas de la base de datos. Así, deberías usar bloques de transacción siempre que tengas un número de sentencias que deben ser ejecutadas todas o ninguna de ellas.
Por ejemplo, considérese el código:
transaction do
david.reintegro(100)
mary.deposito(100)
end
Pruebas
Rails ha sido desarrollado teniendo en cuenta las pruebas y permite probar tu aplicación web de manera exhaustiva. Hay todo un extenso tutorial online que muestra cómo podemos probar una aplicación Rails.
Generadores
Los generadores son los scripts de ayudas que se usan para generar código. Ya hemos usado algunos generadores para crear nuevos controladores y modelos, y al principio de este artículo he mostrado cómo se puede usar un nuevo generador para crear el código de andamiaje.
Rails también soporta generadores creados por el usuario. Por ejemplo, Tobias Luetke ha escrito un Generador de Login que crea todo el código necesario para añadirle a tu aplicación Rails la funcionalidad de registro de usuarios, altas, etc.
Seguridad
A estas alturas todos deberíamos reconocer la importancia de la seguridad en las aplicaciones web. El sitio web de Ruby on Rails tiene un manual sobre seguridad que describe los problemas comunes de seguridad en las aplicaciones web y cómo evitarlos con Rails.
Conclusiones
Rails no es una prueba de concepto ni un framework corriente. Es la siguiente generación de entornos de desarrollo web y los desarrolladores que lo usen crearán sus aplicaciones más deprisa que los que no lo hagan; incluso desarrolladores que trabajen solos pueden ser tan productivos como equipos completos. Y lo mejor de todo: está disponible ya, bajo licencia MIT.
Creo que no ha habido en toda la historia reciente de la programación una mejora comparable en cuanto a productividad.
Recursos
Sitios Web
- Comunidad de Ruby en castellano
- Página oficial de Ruby on Rails en castellano
- Agregador de bitácoras centradas en Ruby y Rails, en castellano
- Si sabes inglés, la mejor manera de aprender Ruby es leerse el libro gratuito Programming Ruby
- Página para proyectos open source con Ruby: RubyForge
Listas de correo
Curt Hibbs vive en St. Louis y es un desarrollador de software con más de 30 años de experiencia en tantas plataformas, lenguajes y tecnologías que serían demasiado numerosas para detallar aquí.
Enlace al artículo original en OnLamp (en ingles)
Seguramente habrás oído hablar de Ruby on Rails, la nueva forma superproductiva de desarrollar aplicaciones web, y te gustaría probarla, pero no tienes ni idea de Ruby o de Rails. Este artículo te guiará paso a paso a través del desarrollo de una aplicación usando Rails. No tratará de enseñarte a programar en Ruby, pero si ya conoces algún lenguaje de programación orientada a objetos no deberías tener ningún problema para seguirlo (al final encontrarás enlaces para aprender más de Ruby)
Pero primero vamos a responder algunas cuestiones candentes antes de remangarnos y ponernos a construir una aplicación web.
¿Qué es Ruby?
Ruby es un lenguaje orientado a objetos puro, con una sintaxis super limpia que hace que programar sea elegante y divertido. En Ruby se combinan con éxito la elegancia conceptual del Smalltalk, la facilidad de uso y aprendizaje de Python y el pragmatismo de Perl. Ruby fue creado en Japon a principios de los 90, pero ha empezado a popularizarse en todo el mundo en los últimos años según han ido apareciendo más libros y documentación en inglés
¿Qué es Rails?
Rails es un framework de código abierto para Ruby que sirve para desarrollar aplicaciones web que acceden a bases de datos. ¿Qué tiene esto de especial? Hay docenas de frameworks por ahí, y la mayoría existen desde hace más tiempo que Rails. ¿Por qué molestarse en aprender otro framework una vez más?
Bien, ¿qué dirías si te contase que puedes desarrollar un aplicación web al menos diez veces más deprisa con Rails que lo que tardarías con un framework típico en Java? Y puedes hacerlo sin sacrificar la calidad de tu aplicación. ¿Cómo es posible?
Parte de la respuesta está en el lenguaje de programación Ruby. Hay muchas cosas que son sencillas de hacer en Ruby pero que ni tan siquiera pueden hacerse en otros lenguajes, y Rails saca partido de esto. El resto de la respuesta reside en los dos principios en que se basa Rails: menos software y convención sobre configuración
Menos software quiere decir que se escriben menos lineas de código para implementar la aplicación. Si el código es pequeño quiere decir que el desarrollo es más rápido y con menos errores, lo que hará que el código sea fácil de entender, mantener y mejorar. En breve veremos cómo Rails pone nuestro código a dieta.
Convención sobre configuración significa que le decimos adiós a esos prolijos ficheros de configuración en XML. ¡En Rails, simplemente, no existen! En lugar de archivos de configuración, una aplicación Rails utiliza una serie de convenciones simples que le permiten avergiuarlo todo mediante reflexión y descubrimiento. El código de tu aplicación y la base de datos que tienes ¡ya contienen todo lo que Rails necesita saber!
Ver es creer
A menudo oímos, como desarrolladores, las exageraciones que se dicen de los productos nuevos. Lo sé, puedo imaginarme esa mirada escéptica que has puesto cuando has leido mis atrevidas afirmaciones. Sí, claro, diez veces más deprisa... ¡seguro!
No pretendo que aceptes esto con la fé del carbonero: te mostraré como comprobarlo por tí mismo. Primero instalaremos el software necesario, y luego continuaremos con el desarrollo de una aplicación web.
Instalación del Software
Vamos a desarrollar esta aplicación web sobre Windows. También puedes seguir el tutorial si usas un sistema Linux o Mac, pero la pantalla será algo diferente de las capturas que se muestran a continuación. Además, tendrás que instalar paquetes desarrollados específicamente para tu sistema. Mira en el apartado Recursos al final de este artículo donde se encuentran enlaces de interés.
Para desarrollar esta aplicación web, necesitamos instalar lo siguiente:
- Ruby
- El framework Rails
- La base de datos MySQL (y el cliente gráfico MySQL-front)
Paso 1: Instalación de Ruby
Figura 1. Programa de instalación de Ruby para Windows
La instalación de Ruby no puede ser más simple:
- Desacarga el último paquete
instalador de Ruby para Windows (se muestra en la figura 1). En el
momento de escribir este artículo, la última versión es
ruby184-16.exe). - Haz doble clic en el ejecutable que has descargado y sigue las instrucciones
del instalador. A no ser que tengas requisitos especiales, simplemente
pulsa
Enterpara aceptar todas las opciones por defecto.
Nota para usuarios de Linux y OS X: El instalador de Windows viene con el gestor de paquetes RubyGems ya instalado. Probablemente te haga falta instalarte RubyGems aparte.
Paso 2: Instalar Rails
Figura 2. Instalación de Rails con RubyGems
A continuación podemos usar el gestor de paquetes RubyGems para descargar e instalar la última versión de Rails, como se muestra en la figura 2:
- Abre una ventana de terminal y ejecuta el comando
gem install rails --remote. - RubyGems instalará además todas las librerías de las que depende Rails. Para cada una de ellas, RubyGems preguntará si quieres instalarla. Responde "y" (yes) a todas.
Paso 3: Instalar MySQL

Figura 3. El asistente de instalación del servidor MySQL.
Nos sigue haciendo falta instalar nuestro servidor de bases de datos. Rails soporta muchas bases de datos distintas, pero nosotros usaremos MySQL.
- Descarga la última versión «esencial» del
instalador de
MySQL para Windows (a día de hoy, la
5.0.18-win32) - Haz doble clic en el instalador (figura 3) y acepta todos los valores por defecto para la instalación típica. Puedes saltarte el paso de registrar una cuenta de usuario en mysql.com.
- Cuando llegues al último panel del instalador, al pulsar en el botón
Finishaparecerá el asistente de configuración. - En el asistente de configuración también puedes aceptar todos los valores por
defecto (standard configuration), excepto en el panel de seguridad (figura 4),
porque a partir de
la versión 4.1.7 MySQL utiliza un nuevo algoritmo de autenticación que
no es compatible con clientes anteriores, incluyendo la versión actual
de rails. Dejando esta opción sin rellenar, podemos acceder a MySQL sin
emplear una clave.
[N. del T: Las versión de Rails que hemos instalado, al ser mucho más reciente
que la que Curt está empleando en su tutorial, ya es capaz de conectar
con MySQL usando la nueva encriptación, de forma que podemos introducir aquí
una clave de administración sin problemas. Nosotros usaremos
root/rollingcomo nombre y clave de administración]
Paso 4: Instalación de MySQL-Front
MySQL-Front es una interfaz gráfica para la base de datos MySQL. Es una aplicación comercial de precio económico pero puedes evaluarla gratuitamente durante 30 días. En este artículo la usaremos para crear nuestra base de datos. Por supuesto, y si lo prefieres, puedes enviar comandos SQL a la base de datos usando la consola de MySQL.
- Descarga la última versión de MySQL-Front (versión 3.2, build 11.2)
- Haz doble clic en el ejecutable de instalación y sigue las instrucciones de instalación (figura 5) Puedes aceptar todos los valores por defecto.

Figure 5.
Instalador de MySQL-Front
Vamos a escribir código
Crearemos un libro de recetas online para poder guardar y compartir las recetas favoritas de todos nosotros. Queremos que nuestro libro de recetas haga lo siguiente:
- Mostrar una lista de todas las recetas.
- Crear nuevas recetas y editar las ya existentes.
- Asignar una receta a una categoría (por ejemplo «postre» o «sopa»).
Puedes crear tu aplicación en el directorio que quieras, nosotros hemos usado c:\rails\recetario. Todos los nombres de directorio y paths que aparecen en este artículo asumen que la aplicación se ha instalado ahí. Si escoges instalarlo todo en otro directorio, ten en cuenta que debes hacer los ajustes necesarios cuando veas directorios de aplicación en el artículo.
También puedes descargar el código del
ejemplo completo y seguirlo con nosotros. Si lo haces, busca en el directorio
cookbook/db/ un archivo que puedes usar para reconstruir la base de datos.
[N. del T: Si te descargas el código de la aplicación del sitio de OnLamp, ten en cuenta
que el código y los esquemas de la base de datos estarán en inglés. Te recomiendo que
sigas el artículo paso a paso.]
Creación de una aplicación Rails vacía
Rails es un framework de aplicaciones web que funciona en tiempo de ejecución pero además es una serie de scripts de ayuda que automatizan muchas de las tareas que hay que hacer cuando se desarrolla una aplicación web. En este paso, vamos a usar uno de estos scripts para crear toda la estructura de directorios y el conjunto inicial de ficheros para comenzar con nuestra aplicación de recetas.
- Abre una ventana de terminal y navega hasta donde quieres que resida tu aplicación.
Nosotros hemos usado
c:\rails. Ejecuta el comando:
rails recetarioSe creará un directorio recetario que contiene todo el árbol de carpetas y archivos que conforman una aplicación Rails vacía.
Figura 6. Una aplicación Rails recién creada
Cómo probar la aplicación web vacía
Una aplicación Rails puede ser desplegada prácticamente en cualquier servidor web, pero durante el desarrollo de la aplicación lo más conveniente es usar el servidor WEBrick, que viene incorporado en Rails. Vamos a arrancar este servidor web y vamos a visitar nuestra aplicación.
- En la ventana de comandos que ya tienes abierta ve hasta el directorio del recetario.
Ejecuta el siguiente comando:
ruby script\serverpara arrancar el servidor (figura 7)
- Ahora abre tu navegador favorito y visita
http://127.0.0.1:3000/. Deberías ver algo parecido a la Figura 8. [Nota del Editor: si no estás siguiendo paso a paso este artículo, estos enlaces probablemente no funcionarán. 127.0.0.1 es una dirección especial reservada para la máquina local]
Figura 7. Arranque del servidor WEBrick
No cierres la ventana del intérprete de comandos que contiene al servidor web ejecutándose, pues lo vamos a utilizar según vayamos avanzado
Figura 8. La página por defecto de Rails
Estructura de directorios de una aplicación Rails
Rail trata por todos los medios de minimizar el número de decisiones que
tienes que tomar así como de eliminar el trabajo innecesario. Cuando usaste el
script de ayuda rails para crear el esqueleto de la aplicación,
Rails creó toda la estructura de directorios de la figura 9. Rails sabe
dónde encontrar todo lo que necesita dentro de esta estructura de
forma que luego no tengas que decírselo. Recuerda, ¡no hay archivos de
configuración por ningún sitio!
Figura 9. Árbol de directorios de una aplicación Rails
El grueso de nuestro trabajo como desarrolladores consistirá en crear y editar
archivos en los subdirectorios de c:\rails\recetario\app.
controllerses donde Rails espera encontrar las clases de nuestros controladores. La misión del controlador es manejar una petición web recibida desde el navegador, es decir, del usuario.viewscontiene las plantillas de visualización que se rellenarán con datos de nuestra aplicación, serán convertidas a HTML y devueltas al navegador del usuario.modelscontiene las clases que modelan los datos almacenados en la base de datos de nuestra aplicación. En la mayoría de los frameworks esta parte de la aplicación puede acabar bastante embrollada, prolija, tediosa... ¡pero Rails lo hace todo tremendamente simple!- Por último, en
helpersse guardan las clases de ayuda que se usan para asistir a las clases de modelos, vistas y controladores. Esto ayuda a que dichas clases se mantengan sin crecer de tamaño, dedicadas y ordenadas.
URLs y controladores
Dentro de un momento crearemos nuestra base de datos y empezaremos a desarrollar nuestra aplicación. En primer lugar, es importante entender cómo funcionan los controladores en Rails y cómo se mapean las URLs a métodos de los controladores.
Las clases de los controladores gestionan las peticiones web del usuario. La URL de la petición se mapea a una clase controlador y un método de esa clase. ¿Cómo funciona todo esto?
Deja abierta la ventana de comandos con el servidor web ejecutándose. Abre
una segunda ventana de comandos y colocate en el directorio base de
la aplicación c:\rails\recetario. Tendrá el aspecto de la
figura 10 dentro de un momento.
Figura 10. El directorio del controlador
del libro de recetas
Vamos a usar otro script de ayuda de Rails para crearnos una nueva clase controladora. En la ventana de terminal, ejecuta el comando:
ruby script\generate controller MiPrueba
Se creará un archivo llamado mi_prueba_controller.rb que contendrá el
esqueleto de una clase MiPruebaController.
En el directorio c:\rails\recetario\controllers haz clic con el
botón derecho del ratón y edita este archivo. Debería tener el aspecto de la
figura 11.
Figura 11. Editando MiPruebaController
¿Y qué es lo que pasa cuando uno visita algo que sabemos que no existe?
Compruébalo: http://127.0.0.1:3000/basura/
La Figura 12 muestra el resultado

Figura 12. Visitando un controlador desconocido
No es muy sorprendente. Ahora intenta abrir http://127.0.0.1:3000/Mi_Prueba/
, que se muestra en la figura 13.
Figure 13. Visitando el nuevo controlador
Vaya, esto es otra cosa. La parte de la URL Mi_Prueba se mapea al nuevo
controlador recién creado. Pero esta vez parece como si Rails hubiera tratado
sin éxito de localizar una acción llamada index.
Vamos a arreglarlo. Añade un método index a la clase del controlador, como en la Figura 14.

Figura 14. El método index de
MiPruebaController
Refresca la vista del navegador, y deberíamos ver algo más parecido a la figura 15.

Figure 15. Resultado del método index
También obtendremos el mismo resultado abriendo http://127.0.0.1:3000/Mi_Prueba/index
Ahora añadamos otra acción al controlador: el método dilbert de la Figura 16.

Figura 16. El método dilbert
Visitemos
http://127.0.0.1:3000/Mi_Prueba/dilbert y veremos algo como lo que
se muestra en la Figura 17.

Figura 17. Resultado del método dilbert
Creo que se capta la idea. Ahora crearemos nuestra base de datos y añadiremos código real a nuestra aplicación de libro de recetas..
Creación de la Base de Datos del Libro de Recetas
Ha llegado el momento de crear la base de datos de nuestro libro de recetas y decirle a Rails cómo acceder a ella. (Esta es la única configuración que vas a encontrar en Rails)
Arranca MySQL-Front y regístrarte en tu instanacia local de MySQL (
localhost) comorootutilizando la claverolling(si es que optaste por introducir una clave en el asistente de configuración de MySQL durante la instalación). Para ello deberás definir una nueva sesión y abrirla, tras lo cual deberías ver algo parecido a la figura 18.
Figura 18. MySQL-FrontHay dos bases de datos ya existentes,
mysqlandtest. Crea una nueva base de datos, llamadarecetario. Ejecuta el comando de menúDatabase>New>Database...e introduce el nombre de la base de datosrecetario, como se muestra en la figura 19.
Figura 19. Creación de una nueva base de datosHaz clic en Ok para crear la base de datos.
Para decirle a Rails cómo encontrar la base de datos, edita el fichero
c:\rails\recetario\config\database.ymly cambia el nombre de la base de datos arecetario. Deja el nombre de usuario comorooty en la claverolling(o lo que corresponda). Cuando acabes, debería tener el aspecto de la figura 20. [N del T: en la última versión de Rails, este fichero tiene muchos comentarios con ejemplos de configuración para distintos conectores de bases de datos]
Figura 20. El fichero de configuración database.yml
Con Rails podemos ejecutar la aplicación en modo de desarrollo, de pruebas o de producción, empleando bases de datos diferentes para cada uno. En nuestra aplicación, por simplicidad, utilizaremos siempre la misma.
Nota del editor: En las últimas versiones de Rails, si se edita este archivo
es necesario reiniciar el servidor web o Rails nunca verá la nueva base de datos
y los pasos siguientes fallarán. Pulsa Ctrl-C o cierra la ventana y vuelve a
lanzar el servidor web.
Creación de la tabla recetas
Nuestro libro de recetas contendrá recetas, así que vamos a crear una tabla en nuestra base de datos para almacenarlas.
En el panel de la izquierda de MySQL-Front, haz clic con el botón derecho en la base de datos del recetario y escoge New>Table... del menú emergente (Figura 21)

Figura 21. Creación de una nueva tabla
Asigna a la tabla el nombre recetas (Figura 22).
Figura 22. El diálogo Add Tabla
Nota importante: MySQL-Front creará de manera automática una clave
primaria llamda Id, pero Rails prefiere llamarla
id (en minúsculas). Lo explicaré más adelante, pero por ahora simplemente cámbialo.
En el panel de la izquierda, escoge la tabla recetas que acabas de crear, y luego a la derecha haz clic con el botón derecho en el campo Id, escoge Properties (figura 23), y cambiale el nombre a id. [N del T: nuevamente, en versiones recientes de MySQL-Front el campo que se genera automáticamente se llama id, con lo que el cambio no es necesario. De todas formas asegúrate de que es así.]

Figura 23. Cambio del nombre de la clave primaria
Añadiendo campos a la Receta
Una vez que tenemos una tabla para las recetas, podemos empezar a añadir
campos para guardar la información de nuestras recetas. Empezaremos creado
un titulo e instrucciones. En algún momento
nos harán falta más campos, pero para empezar nos bastará con estos dos.
Con la tabla de recetas seleccionada, haz click en un área en blanco del panel
derecho y escoge New>Field... (Figura 24).

Figure 24. Añadir un nuevo campo
Crea el campo del título de la receta como varchar(255),
sin permitir valores nulos, de forma que cada receta debe
tener texto de título. En la figura 25 vemos las opciones de la ventana emergente.

Figura 25. Añadir el campo titulo
Repite el procedimiento anterior para crear un campo instrucciones como
text, como se muestra en la figura 26.

Figura 26. Añadir el campo instrucciones
La tabla de recetas debería ser como la de la figura 27

Figura 27. La tabla receta modificada
Ahora empieza lo bueno
Todo lo que hemos venido haciendo hasta este punto ha sido bastante breve e indoloro, pero tampoco ha sido especialmente excitante. Y aquí es donde la cosa cambia. Como vereis, podremos tener los primeros esbozos de nuestra aplicación de recetas en pie y funcionando en un tiempo récord
Creación del modelo
Primero, crea una clase de model Receta que contendrá los datos
de la tabla recetas en la base de datos. En la Figura 28 se observa
dónde debería encontrarse.
Figura 28. La clase del modelo Receta
Abre una ventana de comandos en el directorio del recetario (c:\rails\recetario)
y ejecuta el comando:
ruby script\generate model Receta
Se creará, entre otros, un fichero llamado receta.rb que contendrá el esqueleto
de la clase Receta. Editalo y examina su contenido (Figura 29).
Figura 29. El contenido de receta.rb
En esta definición de clase aparentemente vacía se encuentra el objeto de negocio
de la receta que Rails mapea sobre la tabla recetas de la base de
datos. Entenderás mejor lo que quiero decir dentro de un momento, pero de momento
quiero señalar que esta magia ha ocurrido porque hemos seguido la convención de
nombrado de Rails: un modelo singular de nombre de clase (Receta)
se mapea a una tabla de la base de datos en plural (recetas). Rails
es lo suficientemente astuto y conoce las reglas de pluralización en inglés,
de forma que Company sea mapea a companies, Person
se mapea a people, etc.
Mas aún, Rails dota dinámicamente a la clase Receta de métodos
seleccionar las filas de la tabla recetas y además prepara un
atributo para cada columna de la tabla. En breve veremos una demostración
de esta conexión dinámica entre la clase Receta y
la tabla recetas.
Ya estamos muy cerca de ver algo operativo. Necesitamos crear un controlador para las recetas (figura 30) con acciones para manipular las recetas de la base de datos mediante las operaciones estándar CRUD: creación, acceso, actualización y borrado (del inglés create, read, update, delete). Rails hace que todo sea mucho más fácil de lo que podamos imaginar.
Figura 30. El controlador Receta en su entorno natural
Abre una ventana de comandos en el directorio del recetario
(c:\rails\recetario) y ejecuta el siguiente comando:
ruby script\generate controller Receta
Lo cual creará un archivo llamado receta_controller.rb que contiene el
esqueleto de definición de la clase RecetaController. Editaremos
el archivo y le añadiremos la linea scaffold :receta, como se muestra
en la figura 31
Figura 31. Una sola línea de código en RecetaController
Esta única línea de código insuflará vida a nuestra tabla de la base de datos, definiendo acciones para todas las operaciones CRUD y permitiéndonos de inmediato crear, leer, actualizar y borrar recetas de nuestra base de datos a través de código.
Abre un navegador y visita http://127.0.0.1:3000/receta/new.
Deberías ver algo como la figura 32.

Figura 30. Página de creación de nuevas recetas
¡Esto sí que mola! No hemos hecho gran cosa y ya podemos empezar a rellenar
nuestra base de datos. No lo haremos todavía: primero le añadiremos más campos
a la tabla receta de nuestra base de datos.
Usaremos MySQL-Front para añadir los campos descripcion y fecha entre los campos titulo e instruccones (figuras
33 y 34).

Figure 34. Añadir el campo descripcion

Figure 34. Añadir el campo fecha
Al actualizar el navegador verás una página parecida a la Figura 35.

Figura 35. La nueva página de receta con los nuevos campos
¡Esto ya sí que es increíble!
Bien, vamos a calmarnos un poco y vamos a introducir una receta de prueba. Rellena
los campos como en la figura 36 y pulsa en el botón create

Figura
36. Nueva receta
Deberías ver los resultados de la figura 37

Figura 37. Listado de todas las recetas
Añade otra más siguiendo el enlace «New receta» e introduciendo los datos como en la figura 38.

Figura 38.
Una nueva receta más
Después de pulsar el botón Create deberías ver algo parecido a la figura 39.
Figura 39. Una lista más llena de recetas
Ya tenemos una enorme cantidad de funcionalidad y simplemente hemos construído una base de datos y escrito una única línea de codigo. Bueno, puede que lo que tenemos de momento no sea muy bonito que digamos, pero eso pronto lo arreglaremos.
Mientras tanto, puedes jugar a añadir, borrar y editar recetas. ¡Adelante! Te espero en la siguiente sección.
¿Qué es lo que acaba de ocurrir?
Una sóla línea de código, scaffold :receta le ha dado la vida a todo.
Nos ha permitido empezar a trabajar con nuestro modelo datos:
prácticamente sin trabajo por nuestra parte ha creado las acciones
list, show, edit, y delete.
También ha creado las vistas por defecto para cada una de estas acciones.
Por supuesto estas acciones y vistas son muy planas, no son el tipo de cosas
que querrías que viesen tus usuarios a no ser que sean un poco friquis. Las
buenas noticias son que podemos dejar el andamiaje en su sitio e ir, uno
por uno, proporcionando nuevas versiones de las acciones y las vistas. Cada vez
que tú definas a una de las acciones o vistas, tu versión será la que se usará
en lugar de la versión del scaffold. Cuando hayas terminado,
simplemente tienes que quitar la sentencia scaffold del controlador.
Pero antes de que hagamos eso, ¿te has fijado en las URLs conforme íbamos jugando con el libro de recetas? Rails trata a toda costa de mostrar al usuario unas URLs claras, simples y directas, no largas y crípticas.
Creación de acciones y vistas
La página que muestra la lista de todas las recetas necesita desesperadamente
alguna mejora. La manera de hacerlo es tomar el control del manejo de la
acción list del andamiaje.
Edita receta_controller.rb y añade un método list similar al
de la Figura 40.
Figura 40. El nuevo método list
Abre http://127.0.0.1:3000/receta/list
y deberías ver algo parecido a la Figura 41.
Figura 41. El resultado del nuevo método list
Como acabamos de crear nuestra propia definición de la acción list, Rails
deja de usar la versión del scaffold (o andamiaje), y ha invocado a
nuestro método list y después ha intentado encontrar una
plantilla que mostrar. Dado que no hemos creado ninguna, hemos recibido este
funesto error de «template missing». Creemos nuestra propia plantilla para
la acción list que sólo muestre el título y fecha de cada receta
Cuando creamos nuestro controlador para las recetas, el script
generate controller también creó un directorio para las vistas
donde podemos guardar las plantillas en HTML para que el controlador las pueda
mostrar. Tenemos que crera una plantilla llamada list.rhtml en
c:\rails\recetario\app\views\receta. Si ya has trabajado con páginas
JSP o ASP, te resultará familiar. Simplemente se trata de un archivo HTML
que tiene código Ruby embebido entre las etiquetas <% %> y
<%= %>.
En el directorio c:\rails\recetario\app\views\receta, crea un fichero
llamado list.rhtml que contenga lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<html> <head> <title>Todas las recetas</title> </head> <body> <h1>Libro de recetas - Todas las Recetas</h1> <table border="1"> <tr> <td width="80%"><p align="center"><i><b>Receta</b></i></td> <td width="20%"><p align="center"><i><b>Fecha</b></i></td> </tr> <% @recetas.each do |receta| %> <tr> <td><%= link_to receta.titulo, :action => "show", :id => receta.id %></td> <td><%= receta.fecha %></td> </tr> <% end %> </table> <p><%= link_to "Crear nueva receta", :action => "new" %></p> </body> </html> |
Edita receta_controller.rb y añade la siguiente línea de código
tal y como se muestra en la figura 42 al método list
Figura 42. Listado de todas las recetas
Recarga la página en el navegador y deberías ver algo parecido a la figura 43.
Figure 43. Una lista de receta más bonita
¡Definitivamente tiene mejor aspecto! ¿Cómo ha funcionado?
1 2 3 |
def list @recetas = Receta.find_all end |
Cuando el usuario abre con su navegador http://127.0.0.1:3000/receta/list,
Rails invocará el nuevo método list que hemos acabado de crear. La
línea de codigo del método le pide a la clase Receta que consiga
una colección con todas las receta de la base de datos, asignando la colección
a la variable de instancia @recetas.
A continuación Rails buscará una plantilla que rellenar para devolvérsela al navegador. Nuestra plantilla consiste casi toda en HTML estándar. La acción real ocurre en la siguiente sección de la plantila:
1 2 3 4 5 6 |
<% @recetas.each do |receta| %> <tr> <td><%= link_to receta.titulo, :action => "show", :id => receta.id %></td> <td><%= receta.fecha %></td> </tr> <% end %> |
Este código Ruby empotrado itera sobre la colección de recetas obtenidas por el
controlador. La primera celda de la fila de la tabla crea un enlace a la página
show de la receta. Observa los atributos que se usan en el objeto
de la receta (titulo, id, y fecha). Estos
provienen directamente de los nombres de columnas de la tabla recetas.
Añadiendo categorías al libro de recetas
Deseamos asignar una receta a una categoría (por ejemplo «postre») y poder mostrar una lista con sólo las recetas que pertenezcan a una categoría particular. Para hacerlo, necesitamos añadir una tabla con las categorías a la base de datos, y un campo en la tabla de recetas que especifique a qué categoría pertenece la receta.
En MySQL-Front, crea una tabla categorias . Recuerda cambiar el campo
Id creado automáticamente y llamarlo id, y después crear
un campo nombre de tipo varchar(50). La tabla resultante
debería ser como la de la figura 44.

Figura 44. La tabla categorias
También vamos a necesitar un controlador para la categoría y un modelo para la categoría. Abre una terminal en el directorio de la aplicación y ejecuta los siguientes comandos (figura 45):
ruby script\generate controller Categoria
ruby script\generate model Categoria

Figura 45. Creación del modelo y el controlador para las categorías
Por último, añadimos el andamiaje al controlador de la categoría. Edita
c:\rails\recetario\app\controllers\categoria_controller.rb y añádele
el código de la figura 45.

Figura 46. Andamiaje para las categorías
Visita http://127.0.0.1:3000/categoria/new
y crea dos categorias llamadas Snacks y Refrescos. Cuando hayas terminado, deberías ver algo parecido a la Figura 47.

Figura 47. Un listado con todas las categorias
Asignación de categorías a las recetas
El libro de recetas ya tiene recetas y categorías, pero aún nos hace falta
enlazar unas con otras. Queremos ser capaces de asignar una categoría a una receta.
Para conseguirlo, vamos a añadir un campo a nuestra tabla de recetas para
guardar el id de la categoría a la que pertenezca cada una de las
recetas y además tendremos que escribir una acción edit para las
recetas que proporcione una lista desplegable con las categorías disponibles.
En primer lugar, añadimos un campo categoria_id a la tabla receta
como un int(6) para que coincida con la clave de la
tabla categoria. Los detalles están en la figura 48.

Figura 48. La tabla de receta con su nuevo campo
categoria_id
Con esto almacenaremos el id de la categoría de la receta. Ahora se lo
diremos al modelo de la clase Receta.
Edita c:\rails\recetario\app\models\receta.rb y
c:\rails\recetario\app\models\categoria.rb, añadiéndole una única
línea de código a cada uno de ellos, como se muestra en las Figuras 49 y 50:
Figura 49. Estableciendo relaciones
en el modelo Receta
Figura 50. Estableciendo relaciones en el modelo Categoria
Debería quedar bastante claro que esto le dice a Rails que una receta pertenece a una única categoría y que una categoría puede tener muchas recetas. Estas declaraciones lo que hacen en realidad es generar nuevos métodos para transitar por estas relaciones desde el código en Ruby.
Por ejemplo, si tengo un objeto receta en @receta, seré capaz de averiguar
el nombre de la categoría a la que pertenece usando @receta.categoria.nombre.
De igual manera si tengo un objeto categoria en @categoria podré obtener
una colección con todas las recetas en la categoría accediendo a @categoria.recetas.
Ya podemos escribir nosotros la acción edit de la receta y la plantilla
de forma que podamos asignar categorías. Edita
c:\rails\recetario\app\controllers\receta_controller.rb y añade
el método edit como en la figura 51
Figura 51. El nuevo método edit para el controlador Receta
Con esto creamos dos variables de instancia para usarlas en la plantilla que mostrará la
página de edición de una receta. @receta es la receta que queremos editar (el parámetro id ha llegado con la petición web en la URL).
@categorias es una colección
con todas las categorías que existen en la base de datos. La plantilla utilizará
esta colección para crear un menú desplegable con la lista de categorías.
En el directorio c:\rails\recetario\app\views\receta, crea un fichero llamado
edit.rhtml que contenga la plantilla HTML que sigue a continuación.
Es casi todo HTML, la triquiñuela principal reside en las etiquetas
select y option que crean la lista desplegable
de categorías:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<html>
<head>
<title>Editar Receta</title>
</head>
<body>
<h1>Editar Receta</h1>
<form action="../update/<%= @receta.id %>" method="POST"">
<input id="receta_id" name="receta[id]" size="30"
type="hidden" value="<%= @receta.id %>" />
<p><b>Titulo</b><br>
<input id="receta_titulo" name="receta[titulo]" size="30"
type="text" value="<%= @receta.titulo %>" />
</p>
<p><b>Descripcion</b><br>
<input id="receta_descripcion" name="receta[descripcion]"
size="30" type="text"
value="<%= @receta.descripcion %>" />
</p>
<p><b>Categoria:</b><br>
<select name="receta[categoria_id]">
<% @categorias.each do |categoria| %>
<option value="<%= categoria.id %>"
<%= ' selected' if categoria.id == @receta.categoria_id %>>
<%= categoria.nombre %>
</option>
<% end %>
</select></p>
<p><b>Instrucciones</b><br>
<textarea cols="40" id="receta_instrucciones"
name="receta[instrucciones]"
rows="20" wrap="virtual">
<%= @receta.instrucciones %>
</textarea> </p>
<input type="submit" value="Update" />
</form>
<a href="/recipe/show/<%= @receta.id %>">
Show
</a> |
<a href="/receta/list">
Back
</a>
</body>
</html> |
Puedes ver cómo se usan las variables @receta y @categorias.
Observa la sección que itera sobre todas las categorías para crear
una lista de selección, y fíjate bien en la etiqueta
para ver cómo utiliza la categoría que está asignada a la receta en edición como
la opción seleccionada. Estudia la plantilla y luego... ¡comprueba que funciona!
Visita http://127.0.0.1:3000/receta/list
y edita la receta «Agua helada». Cambia su categoría a «Refrescos», como se
muestra en la figura 52.
Figura 52. Cambio de la categoría de una receta
Antes de avanzar hasta el último paso, asegúrate de que todas las recetas en la base de datos tienen una categoría. Edítalas todas, escoge una categoría y actualizalas. Si no lo haces, saldrán errores en el próximo paso.
Mostrando las categorías en nuestra lista de recetas
Este es el último paso. Modificarás las plantilla de la lista que hiciste antes para visualizar la categoría de cada receta.
Edita el fichero c:\rails\recetario\app\views\receta\list.rhtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<html> <head> <title>Todas las Recetas</title> </head> <body> <h1>Libro de Recetas Online - Todas las Recetas</h1> <table border="1"> <tr> <td width="40%"><p align="center"><i><b>Receta</b></i></td> <td width="20%"><p align="center"><i><b>Categoria</b></i></td> <td width="20%"><p align="center"><i><b>Fecha</b></i></td> </tr> <% @recetas.each do |receta| %> <tr> <td><%= link_to receta.titulo, :action => "show", :id => receta.id %></td> <td><%= receta.categoria.nombre %></td> <td><%= receta.fecha %></td> </tr> <% end %> </table> <p><%= link_to "Crear nueva receta", :action => "new" %></p> </body> </html> |
Ahora pruébala visitando http://127.0.0.1:3000/receta/list. Debería verse
algo parecido a la figura 53.

Figura 53. Listado de recetas con categorías
Ejercicios para el lector
Enhorabuena, acabas de construir una aplicación web con Rails. Por supuesto, aún necesita algo de trabajo, pero ya es funcional.
Aquí hay algunas tareas que podrías hacer:
- Ya no hay forma de eliminar una receta. Añade un botón -o enlace- de borrado a la plantilla de edición.
- En la página principal de recetas no hay ningún enlace a las páginas que te permiten editar categorías. Arréglalo.
- Estaría bien tener una forma de visualizar sólo las recetas que pertenecen a una categoría particular. Por ejemplo, tal vez me gustaría ver una lista de todos los snacks o una lista de todas las bebidas. En la página que lista las recetas, haz que cada nombre de categoría sea un enlace a una página que visualiza todas las recetas de esa categoría.
Este artículo es el primero de una serie de dos. En la segunda parte, implementaremos las tareas anteriores, si bien no tienes por qué esperarnos. Implementarlas por tí mismo puede ser una manera divertida de empezar con el desarrollo en Rails.
Conclusiones
Ruby on Rails ha llevado el desarrollo web a todo un nuevo nivel. Ya no hace falta hacer lo que hasta ahora era un trabajo tedioso, porque Rails lo hace por nosotros. Incluso si tienes que usar una base de datos heredada que no utiliza las convenciones de nomenclatura de Rails, no tienes por qué abandonar las ventajas de productividad que te proporciona: también hay una forma de decirle a Rails explícitamente qué nombres de tabla y columna utilizar para cada cosa.
Ahora que ya has visto de primera mano lo fácil que es crear una aplicación web, ¿por qué ibas a querer hacerlo de ninguna otra manera?
Tal vez tu empresa obligue a utilizar cierto framework particular o lenguaje. Seguro que puedes sacar algunos días para hacer un prototipo de tu aplicación y después decirle a tu jefe: «Ya he terminado nuestra aplicación usando Rails! Si te parece, podemos pasar los próximos meses escribiéndola como estaba originalmente planeada». ;-)
Nota del editor: ¿quieres saber más de Ruby on Rails En marcha con Ruby on Rails, segunda parte y Ajax on Rails.
Recursos
Sitios Web
- Comunidad de Ruby en castellano
- Página oficial de Ruby on Rails en castellano
- Agregador de bitácoras centradas en Ruby y Rails, en castellano
- Si sabes inglés, la mejor manera de aprender Ruby es leerse el libro gratuito Programming Ruby
- Página para proyectos open source con Ruby: RubyForge
Listas de correo
Curt Hibbs vive en St. Louis y es un desarrollador de software con más de 30 años de experiencia en tantas plataformas, lenguajes y tecnologías que serían demasiado numerosas para detallar aquí.
