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í.

por Curt Hibbs (traducción de J. Lupión)

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.

Listado de Gems instaladas
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.

El nuevo código del método new del
controlador Receta
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.

Nueva receta con categoría
Figura 3. Nueva receta con categoria

Tras crear la nueva receta debería verse algo parecido a la figura 4.

listado con todas las recetas
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>
        &nbsp;&nbsp;&nbsp;
        <%= 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.

Diálogo de confirmación al borrar 
una receta
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?

Error al borrar la receta del agua helada
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.

Hemos borrado 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.

añadiendo un layout al controlador  de Receta
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" %>
   &nbsp;&nbsp;
   <%= link_to "Ver todas las recetas", 
               :controller => "receta", 
               :action => "list" %>
   &nbsp;&nbsp;
   <%= 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>
     &nbsp;&nbsp;&nbsp;
     <%= 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.

using a layout with common links
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.

añadiendo el layout al
controlador de las categorias
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>
        &nbsp;&nbsp;&nbsp;
        <%= 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.

showing only snacks
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")

viewing development statistics
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

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í.

por Curt Hibbs (traducción de Juan Lupión)

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

programa de instalación de ruby para windowsr
Figura 1. Programa de instalación de Ruby para Windows

La instalación de Ruby no puede ser más simple:

  1. 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).
  2. Haz doble clic en el ejecutable que has descargado y sigue las instrucciones del instalador. A no ser que tengas requisitos especiales, simplemente pulsa Enter para 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

instalacion de Rails con RubyGems
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:

  1. Abre una ventana de terminal y ejecuta el comando gem install rails --remote.
  2. 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

Asistente de instalación de 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.

  1. Descarga la última versión «esencial» del instalador de MySQL para Windows (a día de hoy, la 5.0.18-win32)
  2. 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.
  3. Cuando llegues al último panel del instalador, al pulsar en el botón Finish aparecerá el asistente de configuración.
  4. 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/rolling como 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.

  1. Descarga la última versión de MySQL-Front (versión 3.2, build 11.2)
  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.

Instalado de MySQL-Front
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.

  1. Abre una ventana de terminal y navega hasta donde quieres que resida tu aplicación. Nosotros hemos usado c:\rails.
  2. Ejecuta el comando:

    rails recetario

    Se creará un directorio recetario que contiene todo el árbol de carpetas y archivos que conforman una aplicación Rails vacía.

Una aplicación Rails recién creada
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\server

    para 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]

Arranque del servidor WEBrick
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

La página por defecto de Rals
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!

Árbol de directorios de una aplicación Rails
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.

  • controllers es 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.
  • views contiene 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.
  • models contiene 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 helpers se 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.

El directorio del controlador 
	del libro de recetas
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.

editando
MiPruebaController
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

Visitando un controlador desconocido
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.

Visitando el nuevo controlador
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.

the index method of MyTestController
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.

resultado del metodo index
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.

el metodo dilbert
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.

the output of the dilbert method
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)

  1. Arranca MySQL-Front y regístrarte en tu instanacia local de MySQL (localhost) como root utilizando la clave rolling (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.

    MySQL-Front
    Figura 18. MySQL-Front

  2. Hay dos bases de datos ya existentes, mysql and test. Crea una nueva base de datos, llamada recetario. Ejecuta el comando de menú Database>New>Database... e introduce el nombre de la base de datos recetario, como se muestra en la figura 19.

    creating a new database
    Figura 19. Creación de una nueva base de datos

    Haz clic en Ok para crear la base de datos.

  3. Para decirle a Rails cómo encontrar la base de datos, edita el fichero c:\rails\recetario\config\database.yml y cambia el nombre de la base de datos a recetario. Deja el nombre de usuario como root y en la clave rolling (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]

    The database.yml configuration file
    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)

creating a new table
Figura 21. Creación de una nueva tabla

Asigna a la tabla el nombre recetas (Figura 22).

the Add Table dialog box
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í.]

renaming the primary key
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).

adding a new field
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.

adding the title field
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.

adding the instructions field
Figura 26. Añadir el campo instrucciones

La tabla de recetas debería ser como la de la figura 27

the modified recipe table
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.

the Recipe model class
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).

the contents of recipe.rb
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.

El controlador Receta en su entorno natural
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

una sola linea de codigo RecetaController
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.

Página de creación de nuevas recetas
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).

adding the description field
Figure 34. Añadir el campo descripcion

adding the date field
Figure 34. Añadir el campo fecha

Al actualizar el navegador verás una página parecida a la Figura 35.

a new recipe page with the new fields
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

a new recipe
Figura 36. Nueva receta

Deberías ver los resultados de la figura 37

Figura 37. Listado de todas las recetas
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.

another new recipe
Figura 38. Una nueva receta más

Después de pulsar el botón Create deberías ver algo parecido a la figura 39.

a fuller list of all recipes
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.

A new list method
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.

the results of the new list method
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

listing all recipes
Figura 42. Listado de todas las recetas

Recarga la página en el navegador y deberías ver algo parecido a la figura 43.

a nicer recipe list
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.

the categories table
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

creating the category model and controller
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.

category scaffolding
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.

a listing of all categories
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.

the recipe table with its new category_id
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:

setting relationships in the Recipe model
Figura 49. Estableciendo relaciones en el modelo Receta

setting relationships in the
Category model
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

the Recipe controller's new edit method
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.

changing the category for a recipe
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.

Listado de recetas con categorías
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

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í.

He traducido al castellano el tutorial How to paginate, sort and search a table with Ajax and Rails, escrito por Julien Barnier.

Con bastante soltura y enfrentándose al problema de paginar una tabla mediante Ajax, Julien nos da un repaso de principio a fin de las técnicas más frecuentes, desde el uso de parciales que modifican sólo ciertas partes del DOM, hasta la creación de observadores que disparan eventos como respuesta a la actualización de un campo (pasando, cómo no, por los inevitables spinners)

Podeis leer (y enlazar) la traducción aquí.

Nota: Este artículo es una traducción (con permiso) de You never know when the brakes might fail, escrito por Damien Tanner y publicado en New Bamboo

Por si fallan los frenos

Con Rails podemos ir a toda máquina a la hora de desarrollar nuestras aplicaciones, pero con esta velocidad sufrimos un mayor riesgo de descarrilar (no puedo resisitrme a hacer comparaciones ferroviarias). Afortunadamente para nosotros Rails (con todo el cariño de Ruby) tiene un arsenal de pruebas soberbio. Muchos de los que conozco aún no han adoptado la mentalidad del desarrollo orientado a pruebas, lo cual es comprensible porque es una manera totalmente nueva de pensar que lleva cierto tiempo para aprenderla y adaptarse a ella. A principio puede parecer complicado apreciar los méritos de la automatización de pruebas, porque puede significar que tardas el doble de tiempo en construir tu aplicación. Pero algún dia una de tus pruebas fallará, investigarás y descubrirás la causa del fallo y te imaginarás qué habría pasado si ese fallo no hubiera sido descubierto a tiempo. A partir de entonces te darás cuentas, de forma definitiva, de la potencia de las pruebas automáticas.

El uso de pruebas por codigo también te da libertad. Por ejemplo, en un eciente proyecto nuestro hicimos hace un par de semanas ciertos cambios estructurales importantes en la base de datos, y con unos 50 modelos hubiera sido un infierno hacer todo lo que hacía falta sin emplear pruebas unitarias. Una batería completa de tests nos permitió hacer los cambios en la base de datos y ver, inmediatamente, qué modelos de la aplicación necesitaban ser modificados y si las modficiaciones que habíamos hecho eran correctas. En última instancia, las baterias de pruebas me permiten dormir por las noches.

Sorprendentemente, todavía hay pocos tutoriales para ayudarnos a la hora de empezar a escribir nuestras pruebas. Sin embargo, las cosas están cambiando deprisa, por suerte. Esperamos que este artículo te ayuda a familiarizarte con los diferentes tipos de pruebas que se usan con más frecuencia.

(Sigue leyendo el resto de la traducción aquí)

Para esta revisión de nuestra aplicación nos hemos planteado los siguientes objetivos

  • Hacer realmente algo con el modelo del usuario. Ya tenemos la posibilidad de dar de alta nuevos usuarios y enviarles una clave de activación por correo… pero no utilizamos esta información de usuario para nada. La idea es guardar algo así como una tabla de puntuaciones con los nombres de los usuarios que han sido capaces de resolver el rompecabezas en menos tiempo y movimientos.
  • Una sugerencia de un lector: incluir la posibilidad de recuperar una cuenta una vez que hemos olvidado la clave (gracias, Neko), ampliando el código generado por el plugin acts_as_authenticated
  • Traducir los mensajes de validación que nos devuelve ActiveRecord cuando tratamos de dar de alta un usuario.
  • Por último, aprovecharemos para hacer un pequeño rediseño de la web. Este último aspecto, siendo más o menos ajeno a Rails, no lo vamos a tratar aquí, pero lo podeis ver directamente en la aplicación

Como siempre, podeis descargar el código de la aplicación aquí.

Read the rest of this entry

En esta nueva revisión del SudokuOnRails vamos a incluir un sistema de registro y alta de usuarios, lo cual nos va a llevará a tratar materias que no habíamos tratado hasta ahora

  • Instalar un plugin de Rails suministrado por terceros (acts_as_authenticated)
  • Crear una base de datos y hacer que nuestra aplicación acceda a ella

Como siempre, tenéis disponible la aplicación online en SudokuOnRails.com y el código fuente está disponible aquí

Pero antes de entrar en materia tenemos algo pendiente actualizarnos a la última versión de Ruby on Rails desde hace mucho, así que empezaremos con el proceso de actualización…

Read the rest of this entry

Furilo avisa que ya está disponible la presentación del Taller de RoR que organizaron en el Hacklab WH2001 – Cielito Lindo. La primera parte se centra en el lenguaje Ruby, y la segunda se adentra en Rails.

Más material para los que quieran aprender con RoR y no tienen muy claro por dónde empezar.

Cabe decir que Rolling with Ruby on Rails fue el tutorial que desató la fiebre de RoR, hace ahora más o menos un año.

El autor, Curt Hibbs, me ha dado permiso para publicar aquí una traducción al castellano, que espero que sea de interés para los recién llegados a mi framework favorito (bueno, en realidad eso de «me ha dado permiso» suena bastante rimbombante… su respuesta ha venido a ser algo así como «Puedes hacer lo que quieras, siempre que dejes mi nombre y un enlace al artículo original»)

He traducido la primera la y segunda parte del tutorial, orientado a Windows, que empieza explicándonos como instalar paso a paso Ruby, Rails y MySQL y finaliza con una pequeña aplicación web.

Cualquier aviso de erratas o comentario en general será bien recibido.

Dado que desde que cambiamos el aspecto de nuestra aplicacíón recibimos decenas de visitas diarias, deseamos instalar un contador para ver de dónde viene la gente (ejem, lo de que deseamos poner un contador es cierto, lo de que recibimos visitas es una pequeña exageración). En esto de los contadores los hay para todos los gustos, desde los todopoderosos contadores de Google Analytics hasta los de Nedstat que tienen la simpática costumbre de meter publicidad intrusiva en la web que los incluye. También existen contadores basados en scripts PHP que se instalan en nuestro propio servidor, como Mint e incluso ya existe un contador basado en Rails, Weed. Nosotros optaremos por una solución más tradicional: Statcounter

Una solución rápida

Con Statcounter la cosa es muy sencilla, tras darnos de alta y configurar nuestro sitio web, nos proporcionan un fragmento de código mezcla de Javascript y HTML que debemos incluir en nuestra página. La primera aproximación es incluir este código directamente en nuestra plantilla de aplicación (app/views/layouts/application.rhtml).

Esta solución tiene dos inconvenientes: el primero es que el fragmento de código es relativamente largo y si lo incluimos en nuestra plantilla principal ésta se complica bastante. El segundo inconveniente es más conceptual: el contador no aporta nada a nuestra aplicación, debería estar fuera de la plantilla principal y, a ser posible, en un sitio apartado, lejos del resto de cosas.

Y además, no me serviría de ejemplo para lo que viene a continuación.

Introducción a los Parciales

Los parciales (partials) son fragmentos de .rhtml (es decir, HTML con Ruby embebido) que pueden ser incluidos desde otra vista. Los únicos requisitos son dos: que el nombre del fichero .rhtml donde guardemos el parcial empiece por ’_’ y que incluyamos el parcial desde nuestra vista principal usando <%= render(:partial => “miparcial.rhtml”) %>.

Por defecto, Rails supone que los parciales viven en el mismo directorio de la vista del controlador que los incluye (app/views/), pero si en la clave :partial incluimos una ruta, Rails la construirá a partir de app/views, de forma que podamos compartir este parcial entre diferentes controladores.

Manos a la obra

Simplemente creamos el fichero app/views/shared/_statcounter.rhtml , y pegamos en él el fragmento de código de Statcounter para nuestra web. Luego, en app/views/layouts/application.rhtml añadimos en el lugar adecuado

<%= render(:partial => "shared/statcounter") %>

Y no tenemos que hacer nada más. Teneis la nueva versión aquí y el código fuente, aquí

Más sobre los parciales

La utilidad de los parciales va más allá de incluir fragmentos de HTML en nuestra aplicación, como hemos hecho hoy. De hecho, lo más interesante de los parciales es que, al llevar Ruby embebido, pueden recibir objetos de nuestra aplicación y manipularlos.

Por ejemplo, podríamos tener un parcial para mostrar una lista de la compra de nuestra aplicación, que recibiese los elementos del carrito desde la vista de un controlador y que tuviese código Ruby para, por ejemplo, sumar el total de los elementos para mostrar el precio, con IVA o sin IVA según alguna variable escogida por el usuario, algo así como

<%= render(:partial => 'carrito', 
           :object => @articulos, 
           :locals => { :con_iva => @mostrar_iva }) %>

(En el hash locals podemos definir las variables locales que serán visibles por el parcial)

No es muy difícil darse cuenta de que nuestra versión de Sudoku on Rails necesita urgentemente un lavado de cara. Nos gustaría darle algo de vida al aspecto de la aplicación, y a eso nos vamos a dedicar en esta nueva edición del tutorial. Gracias a la separación de la vista del resto de nuestra aplicación, podremos hacerlo sin escribir ni una línea de código.

El nuevo aspecto final podéis verlo aquí y podéis descargar el nuevo código desde aquí

Cómo sirve Rails nuestras páginas

Todo lo que cuelga del directorio public/ de nuestro proyecto Rails es servido de manera similar a como lo haría un servidor web tradicional. De hecho, es servidor por el servidor web bajo el que corramos nuestra aplicación, sin pasar por el intérprete Ruby.

Para el caso del contenido dinámico (y como ya vimos en el post anterior) cuando se invoca una acción de un controlador se sirve un fichero .rhtml, la vista por defecto que se sirve es views/layouts/controlador/accion.rhtml, o bien en nuestro controlador podemos indicar otra vista mediante render_action_. Estos ficheros .rhtml consisten en fragmentos de HTML mezclados con código Ruby.

Pero esto no es todo, el código generado por nuestra vista o layout no es lo que se envía al navegador. De momento basta con que sepamos que podemos definir una plantilla o vista a nivel de aplicación (app/views/layouts/application.rhtml) en la que se encaje el texto HTML generado por las vistas de cualquier controlador usando el tag content_for_layout

Obviamente, RoR no acaba aquí sino que va bastante más lejos, pero de momento nos bastará con quedarnos con esto.

Estrategia para trabajar lo menos posible

Para nuestro lavado de cara, nos bastará con realizar nuestro diseño (o bien, como en este caso, fusilar uno de OSWD ) y copiar los recursos estáticos en su correspondiente subidrectorio, public/images y public/stylesheets por lo general). Luego, sólo tenemos que generar algo parecido alindex.html de nuestro diseño usando application.rhtml y recordar incluir la hoja de estilos no con una referencia directa sino con stylesheet_link_tag. Igualmente si incluyésemos imágenes, usaríamos image_tag, tal y como nos explican en esta página del wiki de RoR

Por cierto, hemos usado este tema diseñado por Minimal Laboo

Páginas adicionales estáticas

En nuestra nueva versión, queremos tener una pequeña página que de alguna información sobre el juego del sudoku. Esta página en teoría sería contenido meramente estático así que podríamos incluirla directamente como public/acerca.html y hacer referencia a ella desde nuestras plantillas.

Pero esta página tendría que ser un fichero HTML estático, de forma que no podríamos aprovechar la descomposición de la que hemos hablado antes (una plantilla principal RHTML + código RHTML generado por el controlador). Si decidimos cambiar el aspecto de nuestra aplicación modificando application.rhtml, tendremos que editar a mano este fichero. Mala cosa.

La posibilidad más sencilla para salir al paso de este problema es inventarnos una nueva acción de nuestro controlador, llamada acerca, cuyo código es trivial:


    def acerca

    end

Por defecto, Rails cargará la vista acerca.rhtml donde, sin complicarnos la vida, escribimos en HTML tradicional una pequeña descripción del juego y ponemos algunos enlaces (en el código que os podeis descargar veréis que en la acción se hace una cosita más: se borra el contenido de flash[:note] para no repetir el último mensaje visualizado por el controlador)

De esta manera, nuestra página “Acerca de…” (que por lo demás no tiene contenido dinámico) tendrá el aspecto global de nuestra aplicación de manera inmediata. El inconveniente es que esta página es servida por Rails, no por el servidor web, y supondrá una carga adicional en nuestro servidor.

En Design-Nation también se apuntan a lo de los tutoriales. En este caso se trata de una aplicación para gestionar la lista de regalos recibidos en Navidades (¡eso sí que es original!). También se centrarán en el desarrollo con RoR sobre Mac, con un entorno muy parecido al mío: un Mac mini con OSX (¿casualidad?)

Introducción

Continuamos hoy la serie de artículos tutoriales sobre Ruby on Rails En el anterior habíamos comenzado el bosquejo de una versión web del conocido juego del Sudoku. En esta entrega repasaremos alguno