La Aventura de Ruby on Rails (Parte 3): Hola Mundo

martes, abril 21, 2009


Con la instalación de Rails obtenemos un nuevo comando de consola, rails, que se usa para construir una nueva aplicación web.

Se preguntarán: ¿Por qué demonios necesito un comando para crear un nuevo proyecto? o quizás digan: Soy un programador que dobla cucharas con la mente ¿Por qué no puedo crear mi proyecto desde cero usando mi editor de texto favorito? Bueno, de hecho, sí se puede crear un proyecto de Rails usando solo un editor de texto y algunos directorios, pero resulta que el comando rails hace un montón de magia tras la cortina para que nuestra aplicación trabaje OUT OF THE BOX con la mínima configuración explícita. Es importante resaltar que la filosofía de Rails es "Convención sobre Configuración".

Además de toda la magia para evitar la configuración, Rails tiene una estructura de directorios muy interesante y cada uno tiene una función bien definida. La imagen a continuación muestra la estructura de un proyecto llamado test:




  • app: Contiene los archivos de Modelo, Vista y Controlador

  • components: Almacena los componentes reutilizables

  • controllers: Guarda todos los controladores

  • helpers: Almacena modulos utilitarios de las vistas

  • models: Contiene todos los modelos

  • views: Almacena todas las vistas

  • config: Guarda toda la información de configuración del proyecto y los parametros de conexión a la base de datos

  • db: Contiene la información de los esquemas y de las migraciones de la base de datos

  • doc: Almacena la documentación autogenerada

  • lib: Aloja todo el código que no pertenece exclusivamente a la aplicación (plugins, etc)

  • log: Almacena los reportes producidos por la aplicación (y por el framework)

  • public: Es la cara externa de la aplicación. El servidor web lo toma como directorio base de la aplicación y lo accesible desde el navegador.

  • script: Guarda todos los scripts utilitarios de Rails

  • test: Contiene los test unitarios, test funcionales, mocks y fixtures

  • tmp: Almacena los archivos temporales de sesiones, cache y cookies

  • vendor: Cumple la misma función que lib pero para el código de terceras partes


Lo que realmente nos interesa por los momentos es la carpeta app y todo su contenido; ahí es donde ocurrirá toda la diversión xD

Vamos a crear entonces nuestra primera aplicación de prueba para demostrar los conceptos básicos. Abrimos un terminal y navegamos hasta el directorio donde queremos crear el proyecto, luego ejecutamos:

$ rails test
create
create app/controllers
create app/helpers
create app/models
.. ..
.. ..
create log/production.log
create log/development.log
create log/test.log


Ese comando crea el directorio test con toda la parafernalia y la magia de Rails (directorios, configuraciones, etc). Probemos ahora el script utilitario server para cargar WEBrick (un servidor web que trae Ruby por defecto) y verificar que todo está en orden.

$ ruby script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2009-04-21 11:37:30] INFO WEBrick 1.3.1
[2009-04-21 11:37:30] INFO ruby 1.8.7 (2008-08-11) [i486-linux]
[2009-04-21 11:37:30] INFO WEBrick::HTTPServer#start: pid=5199 port=3000


Vamos a nuestro navegador favorito y accedemos a la aplicación con la ruta http://localhost:3000. WEBrick usa por defecto el puerto 3000 pero podemos cambiarlo al puerto de nuestra preferencia ejecutando el server con el parámetro -p y el número del puerto, por ejemplo:

$ ruby script/server -p 8080



Rails es un framework netamente MVC y como tal se basa en un flujo de información de un componente a otro. Primero acepta la solicitud proveniente de un navegador, decodifica la petición para encontrar el controlador y llama una acción de ese controlador. El controlador entonces invoca una vista particular para mostrar el resultado de vuelta al usuario.

Para crear nuestro Hola Mundo necesitamos un controlador y una vista. No hace falta un modelo ya que no estaremos trabajando con ningún tipo de datos.

Así como usamos el comando rails para generar el proyecto, usaremos el script generate para crear un controlador. Supongamos que queremos llamar a nuestro controlador Prueba:

$ ruby script/generate controller Prueba
exists app/controllers/
exists app/helpers/
create app/views/prueba
exists test/functional/
create app/controllers/prueba_controller.rb
create test/functional/prueba_controller_test.rb
create app/helpers/prueba_helper.rb


El controlador se ha creado en app/controllers/prueba_controller.rb. Si examinamos el código fuente veremos algo como:

class PruebaController < ApplicationController
end


El controlador es bastante simple, una clase PruebaController que hereda de ApplicationController y por consiguiente tiene todos sus métodos. Es importante resaltar que Rails usa una convención de nombres que poco a poco iremos conociendo, por ejemplo para los nombres de las clases usa el estilo CamelCase, para los nombres de los métodos usa minúsculas separadas por guión bajo y así sucesivamente.

Ahora nos toca personalizar un poco nuestra nueva clase; agreguemos una acción llamada saludar:

class PruebaController < ApplicationController
def saludar
end
end


Por los momentos la acción saludar no hará nada porque la tarea del controlador es preparar el terreno y la información para que la vista sepa qué mostrar. En esta aplicación no hay nada que preparar, así que una acción vacía será más que suficiente.

Veamos como acceder a esta nueva acción. Rails asocia las URL con la aplicación; la primera parte de la URL identifica la aplicación, la siguiente el controlador y la última la acción a invocar. El siguiente ejemplo ilustra mejor:



Si vamos a esa URL en nuestro navegador veremos una página como la siguiente:



No hay que alarmarse por el error, se debe a que hemos definido un controlador con una acción pero no hemos creado una vista. Las vistas deben ir asociadas con las acciones del controlador y se almacenan en el directorio app/views. Allí deberiamos tener un directorio por cada controlador creado y dentro de esos directorios van las vistas de cada acción. En este caso debemos crear una vista llamada saludar.rhtml dentro del directorio app/views/prueba. El código fuente de esa vista debería ser algo como:

<html>
<head>
<title>Hola Mundo</title>
</head>
<body>
<h1>Hola Mundo! desde Rails</h1>
</body>
</html>


Intentemos de nuevo abrir la dirección http://locahost:3000/prueba/saludar en nuestro navegador y voilá! Ahora si tenemos una vista =D



Hasta el momento nuestra página es vulgar y aburrida... vamos a cambiar esa situación; ¡agreguemos contenido más dinámico!

Una de las formas más simples de añadir contenido dinámico a una vista es incrustando código Ruby al más puro estilo PHP. Las vistas deben tener extensión .rhtml, porque de esa forma le indicamos a Rails que ese archivo debe ser interpretado usando el sistema ERb (de Embbeded Ruby).

Todo el contenido escrito en HTML es pasado al navegador directamente pero el contenido que esté encerrado entre los símbolos <%= y %> es intrepetado y ejecutado como código Ruby. El resultado de esa ejecución se convierte a cadena de texto y se reemplaza in situ por la secuencia anterior para entonces generar una salida HTML pura hacía el navegador.

Aclarado ese punto pasemos al controlador para preparar la información que mostrará la vista. Calculemos, por ejemplo, la hora actual agregando unas líneas al controlador. El código debería quedar así:

class PruebaController < ApplicationController
def saludar
t = Time.now
@time = t.strftime('%H:%m:%S')
end
end


Y ahora actualizamos la vista para que muestre la variable @time:

<html>
<head>
<title>Hola Mundo!</title>
</head>
<body>
<h1>Hola Mundo! desde Rails</h1>
<p>Son las <%= @time %></p>
</body>
</html>


Ruby suele definir las variables de una clase con una arroba (@) al comienzo del nombre. Para enviar contenido a la vista usamos estas variables de instancia del controlador, pero... ¿Cómo puede la vista leer una variable que es privada del controlador? Pues sencillo, Rails hace una de David Cooperfield para que la vista pueda leer a la fulana variable xD.

Sin más preámbulo, nuestra aplicación debería verse así:



Esta página no es la madre del dinamismo pero al menos cambiará con cada actualización xD

Aquí termina el Hola Mundo. Más adelante estaré publicando una aplicación un poco más elaborada donde se use una base de datos e interactuemos con los modelos.

Cambio y fuera.

5 comentarios:

Gabriel dijo...

Grandisimo, acabas de salvarme la vida xDD

afm dijo...

Muy bueno, esto era lo que estaba buscando sencillito pero al grano, chido amigo

Anónimo dijo...

disculpa, al cargar el servicio me marca un error:
$ ruby script/server

ruby: No such file or directory -- script/server (LoadError)


he seguido cada paso pero no salgo de ahi :(

Anónimo dijo...

Hola, he estado leyendo algunos post, pero el tuyo es el mejor xD, que buen trabajo amigo te felicito. Lograste aclararme muchas dudas y vacios que tenia de los otros tutoriales :D.

Lucas Corso dijo...

Buen tuto, saludos.