Vamos a ver cómo se empieza una aplicación web con Ruby on Rails a las 2:45 (de la noche) después de haber seguido la traducción de SobreRailes de la primera parte del tutorial de Curt Hibbs Rolling with Ruby on Rails. Obviamente tengo algo de sueño, así que me disculpo anticipadamente por los gazapos de mi escritura.

Vamos a lo que vamos.

El tutorial emplea un ejemplo clásico de recetas de cocina clasificadas en categorías, que se parece mucho a un trozo de un proyecto personal que tengo aparcado desde hace tiempo: El Tesorero. Lo que voy a hacer a continuación es comenzar una aplicación y escribir una parte mínima, pues esta entrada es una chuleta rápida para cuando tenga que repetir esta operación. Por ello trataré de hacer un resumen muy escueto y rápido, con las explicaciones mínimas, a modo de recordatorio. Aviso para que nadie piense que esto es un tutorial, el tutorial está aquí.

El alojamiento web que voy a utilizar es DreamHost, que soporta Ruby on Rails con o sin FastCGI (aunque sin él va muy lento). Un buen sitio donde empezar a leer si quieres usar Rails en Dreamhost es rails.dreamhosters.com/. Sólo con seguir las instrucciones mínimas para usar Rails sin FastCGI ya es suficiente para el ejemplo de hoy.

En DreamHost ya está instalado todo el software que voy a necesitar, por lo que toda la parte de instalación de Ruby on Rails del tutorial me la salto y paso directamente a crear una aplicación Rails vacía:

cd ~/rails
$ rails bursar

Mi directorio ~/rails es donde he decidido que voy a guardar mis aplicaciones Rails, naturalmente puede ser cualquier otro directorio. El comando rails bursar crea un directorio bursar con todo el esqueleto de la aplicación dentro. Verás que poco voy a tener que escribir.

Mi aplicación comenzará siendo una simple lista de cuentas, que serán simplemente entidades que contienen dinero. Cada cuenta tiene un número de identificación de hasta 20 caracteres, una descripción, un banco (opcional), una moneda (€ por defecto). Para controlar ciertos detalles del comportamiento, cada cuenta debe pertenecer a un tipo determinado, aunque de momento esto no me preocupa.

En primer lugar, hay que hacer que la aplicación sea accesible desde alguna URL, por ejemplo bursar.miguev.net/demo/

$ cd bursar
$ chmod 755 log/ public/ public/dispatch.*
$ cd ~/bursar.miguev.net
$ ln -s ../rails/bursar/public/ demo

También hay que asegurarse de que todos los ficheros ~/rails/bursar/public/dispatch.* comiencen con una línea shabang adecuada, por ejemplo:

#!/usr/bin/ruby1.8

Al visitar bursar.miguev.net/demo/ se vería algo como esto:

  • La página por defecto de Rails

Lo primero será crear una tabla en alguna base de datos SQL donde pueda almacenar los datos de las cuentas. Utilizo MySQL por costumbre, pero también se pueden utilizar PostgreSQL y SQLite3 (como mínimo).

$ cat db/account.sql
DROP TABLE IF EXISTS `accounts`;
CREATE TABLE `accounts` (
`id`            int(6) unsigned NOT NULL auto_increment,
`number`        varchar(20)             NULL UNIQUE,
`kind`          varchar(255)    NOT NULL default 'Cash',
`currency`      char(3)                 NOT NULL default 'EUR',
`descript`      varchar(255)    default NULL,
`bank`          varchar(255)    default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
$ mysql -p bursar_devel < db/account.sql

Para que la aplicación Rails pueda acceder a la base de datos habrá que configurarla con los datos de conexión (servidor, usuario, clave, etc). Esta es la única configuración que hay que hacer: editar el fichero config/database.yml para que se parezca a esto:

development:
adapter: mysql
host: db.bursar.miguev.net
database: bursar_devel
username: bursar
password: supersecreto
test:
adapter: mysql
host: db.bursar.miguev.net
database: bursar_test
username: bursar
password: supersecreto
production:
adapter: mysql
host: db.bursar.miguev.net
database: bursar_demo
username: bursar
password: supersecreto

Hay un detalle que conviene no olvidar: hay tres bases de datos en una aplicación Rails: una para desarrollo, otra para pruebas (test) y otra para producción. La segunda se borra cada vez que se ejecutan los tests, así que no dejes ahí dentro nada que no quieras perder.

Aquí empieza lo bueno, vamos a crear un modelo, mira que difícil:

$ script/generate model Account

Más adelante puede que modifique este modelo, de momento se queda así:

$ cat app/models/account.rb
class Account < ActiveRecord::Base
end

Ahora el más difícil todavía, crear el controlador:

$ script/generate controller Account

Cuidado, que aquí hay que escribir una línea de código para dejar esto así:

$ cat app/controllers/account_controller.rb
class AccountController < ApplicationController
scaffold :account
end

Listo. Colocado el andamio (scaffold) ya podemos empezar a trabajar añadiendo cuentas en http://bursar.miguev.net/demo/account/new y gestionándolas desde http://bursar.miguev.net/demo/account/ con la interfaz básica proporcionada por el andamio.

Sin embargo, la interfaz andamio es demasiado genérica. Está bien para tener algo que funciona, pero probablemente no funcione al gusto del consumidor. Vamos a cambiar esto, empezando por la lista de cuentas.

Llegados a este punto sería interesante leer algo sobre la arquitectura MVC (Modelo-Vista-Controlador). Lo que vamos a hacer es escribir una vista y modificar el controlador. Las vistas en Rails se escriben en ficheros .rhtml de código HTML con incrustaciones de Ruby. Creamos el fichero ~/rails/bursar/app/views/account/index.rhtml con este contenido:

<html>
<head>
<title>El Tesorero -- Cuentas</title>
<link href="/css/biglist.css" type="text/css" rel="StyleSheet">
</head>
<body>
<h1>Cuentas</h1>
<% if @accounts.empty? %>
<p>¿No tienes ninguna cuenta? Venga,
<%= link_to "créate una", :action => "new" %>, ¡es gratis!</p>
<% else %>
<div id="accountslist">
<ul id="accountslist">
<% @accounts.each do |account| %>
<li>
<%= link_to account.name, :action => "show", :id => account.id %>
<% if account.number != "" %>
<p class="accountnumber"><%= account.number %></p>
<% end %>
<p><%= account.descript %></p>
<p>Cuenta de tipo
<em><%= account.kind.downcase %></em>
<% if account.bank != "" %>
en <%= account.bank %>
<% end %>
</p>
</li>
<% end %>
<li><%= link_to "Crear cuenta nueva", :action => "new" %></li>
</ul>
</div>
<% end %>
</body>
</html>

Y añadimos tres líneas al controlador:

class AccountController < ApplicationController
scaffold :account
def list
@accounts = Account.find_all
end
end

Ya está, con esto hemos cambiado la vista de inicio (/index) en dos patadas. Ahora sólo falta que el programador añada funcionalidades y el diseñador le añada atractivo sexvisual, a ser posible sin pelearse entre ellos.

Esto no ha hecho más que empezar ;-)

Actualizado: he modificado la vista account/list basándome en esta CSS para hacerla más agradable.