Aprendiendo Ruby on Rails

Conoce de afuera hacia adentro - Outside-in - el desarrollo de aplicaciones web con el marco de trabajo de Ruby on Rails 5. Aprender de la naturalidad de un lenguaje de programación como Ruby y de cómo Ruby on Rails 5 explota nuestra productividad.

Mario Alberto Chávez Cárdenas

Contenido

Capítulo 2 - Ruby on Rails, el desarrollo ágil de aplicaciones web

Ruby on Rails es un marco de trabajo para el desarrollo de aplicaciones. Ruby on Rails es considerado una herramienta que permite desarrollar aplicaciones web modernas de forma muy rápida.

Parte de esto se debe a que Ruby on Rails provee de una serie de convenciones que permiten al desarrollador enfocarse en la parte importante de la aplicación y no en los detalles que no agregan valor a la aplicación web.

A diferencia de los marcos de desarrollo que surgieron a finales y principios de los 90's, Ruby on Rails es un marco de desarrollo que nació a partir de aplicaciones reales y como vamos a ver un poco más adelante, fue el parteaguas del paradigma de desarrollo web, inclusive podríamos hablar de una época pre y post Ruby on Rails.

En el capítulo anterior vimos como es que el lenguaje Ruby está diseñado para que los desarrolladores sean felices y Ruby on Rails no se aleja mucho de la misma ideología.

Historia

Ruby on Rails cumple 10 años en este 2014, en términos de software podemos concluir que es una herramienta madura en su versión 4.0.

Fue en el 2003 cuando David Heinemeier Hansson inició con el desarrollo de Ruby on Rails. Como se mencionó anteriormente Ruby on Rails - o simplemente Rails como lo mencionaré de forma indistinta en el resto del libro - nació a partir de un producto real, de Basecamp el producto estrella de la entonces 37 Signals.

David inició el desarrollo de Basecamp en Ruby y encontró patrones que no eran específicos a Basecamp pero que podían reutilizarse para el desarrollo de aplicaciones web. Esto sucede en una época en donde empresas como Microsoft y las extintas Sun Microsystems y Bea Logic empujaban para ser los líderes del desarrollo web visual, tratando de emular la experiencia del desarrollo de aplicaciones para escritorio hacia el Web.

La primera versión pública de Rails la anunció David el 25 de Julio del 2004, fue la version 0.5.0 y la llamó "The end of vaporware!". Con el anuncio David describió a Rails como:

Ruby on Rails es un marco de desarrollo web para Ruby. Rails incluye una solución para cada letra de MVC: ActionPack para el Controlador y las Vistas, ActiveRecord para el Modelo.
Al ser un marco de desarrollo Full Stack, Rails permite el concepto de Don't Repeat Yourself o DRY, así como favorece a la introspección y extensiones al momento de ejecución en lugar de archivos de configuración, esto posteriormente lo conocimos como Convention over Configuration.

Para el 15 de diciembre del 2005 Ruby on Rails vio el anuncio de la versión 1.0.

Ruby on Rails fue la inspiración para desarrolladores en otros lenguajes como Java, Groovy, PHP, etc. para crear marcos de desarrollo parecidos o modelados bajo las ideas de Ruby on Rails.

Beneficios

Uno de los beneficios principales de Ruby on Rails es el concepto de Convención sobre configuración el cual nos elimina temas como el decidir como estructurar nuestra aplicación de Ruby on Rails.

Esto hace que la anatomía de una aplicación de Rails sea entre un 80% y 90% parecida en todas las aplicaciones de Rails. La curva de aprendizaje para desarrolladores que se integran a una aplicación de Rails en la que ya hay un avance en su desarrollo es menor.

Un punto importante en Rails es que con la configuración por omisión es posible empezar el desarrollo y no perder tiempo en esos detalles, más adelante si es necesario se puede ir ajustando la configuración.

Ruby on Rails provee de una serie de generadores que nos permiten prototipar y realizar un desarrollo acelerado de conceptos e ideas. Un ejemplo de que tan rápido se puede desarrollar con Ruby on Rails es el concurso Rails Rumble donde sólo se cuenta con 48 horas para desarrollar una aplicación.

Como parte del desarrollo de aplicaciones con Rails, también se ofrece la posibilidad de realizar pruebas automáticas para las diferentes areas de nuestra aplicación. Las pruebas son un medio para dar certidumbre y asegurarse que aún con cambios futuros la aplicación tendrá un comportamiento mínimo esperado.

Se dice que Rails agrega mucha Magia al desarrollo de aplicaciones, pero no es Magia, simplemente Rails nos evita de tener que tomar toda una serie de decisiones en nuestra aplicación, por ejemplo ¿Cómo nos vamos a conectar a nuestra base de datos?, ¿Cómo organizamos el código en nuestro proyecto?, etc. El concepto de Magia desaparece una vez que entendemos los patrones y convenciones de una aplicación de Rails.

Rails y patrones de diseño

Como se mencionó anteriormente Ruby on Rails adoptó algunos patrones de diseño que ayudan a que todas las aplicaciones de Rails tengan la misma anatomía. Los siguientes conceptos forman parte intrínseca de la raíz de Rails y sirvieron para ayudar a la popularidad del marco de trabajo.

MVC

Ruby on Rails popularizó el patrón de MVC - Model View Controller - formulado por Trygve Reenskaug en la década de los 70's. El patrón describe la forma en como se debería de realizar la interacción de un usuario de un sistema y un sistema.

Desde el punto de vista del sistema, éste se divide en 3 componentes principales: el Modelo, la Vistas y el Controlador. Cada componente tiene responsabilidades únicas. El trabajo de los 3 componentes en conjunto permiten responder a usuario del sistema.

MVC

  1. Modelo: Representa datos en forma de un sólo objeto o un grupo de objetos, en el caso de Rails, un modelo es un objeto o una colección de objetos de ActiveRecord, que como vamos a ver más adelante es otro patrón de diseño.
  2. Vista: Es la representación visual del modelo, es decir es la interfase gráfica que le permite al usuario visualizar la información del modelo. En el caso de Rails una vista es una plantilla de HTML y código de Ruby empotrado que al ser procesada genera el código de HTML final que es enviado al navegador.
  3. Controlador: Tiene la responsabilidad de recibir una solicitud del usuario, determinar si se requiere de datos del modelo y pasar los datos al contexto de la vista para que se genere el HTML que será enviado al navegador.

ActiveRecord

ActiveRecord es un patrón que ayuda a la interacción de una programa con una base de datos. De acuerdo a Martin Fowler, ActiveRecord es un objeto que representa un registro en una tabla o vista, encapsula el acceso a la base de datos y puede contener lógica.

En Rails un Modelo es un objeto de ActiveRecord con el comportamiento anteriormente mencionado.

REST

REST significa Transferencia de Estado Representacional, en términos simples REST es un estilo de arquitectura para sistemas distribuidos como el WWW. REST provee entre otras cosas de consistencia en el estilo de la arquitectura a través de algunas restricciones para dicha arquitectura.

El concepto de REST fue introducido por Roy Thomas Fielding en el 2000 como parte de su tesis doctoral.

Cada restricción definida en REST trae consigo beneficios desde portabilidad, visibilidad, estabilidad y escalabilidad.

  1. Cliente/Servidor: A través de esta restricción se busca el separar las responsabilidades de la interfase gráfica con el proceso y almacenamiento de información. Lo que permite que ambas partes puedan evolucionar de forma independiente.
  2. Sin estado: La interacción del cliente/servidor debe de no tener estado, es decir cada solicitud al servidor debe contener toda la información necesaria para que el servidor desde su contexto entienda de que se trata la solicitud.
  3. Cacheable: Cada respuesta del servidor debe de ser marcada como cacheable o no y el cliente debe de decidir si reutiliza esa respuesta o necesita una nueva.
  4. Interfase uniforme: Es una forma de simplificar la interfase a través de la que se conectan el cliente/servidor y a la ves desacoplar la implementación de los servicios o procesos que intervienen.
  5. Un sistema capas: Permite la organización en capas de componentes que no ven más allá de su capa inmediata y que permite manejar la complejidad de un sistema agregando o eliminando componentes.
  6. Código bajo demanda: Es posible que el servidor envíe código al cliente para modificar o extender su comportamiento.

Hay mucho más de que hablar sobre REST pero por el momento con lo que se menciona en esta sección es suficiente; más adelante en el transcurso del libro volveremos a tocar el tema y utilizaremos elementos arquitecturales de REST para ver de que forma se integran en la ideología de Rails.

Rails en el mundo real

Durante una época, Ruby on Rails fue muy popular entre Startups, muchas de las cuales el día de hoy son empresas perfectamente establecidas y reconocidas.

El ejemplo más representativo, sobre todo porque fue a partir de esta aplicación de como nació Ruby on Rails, es Basecamp. Aplicación para organizar proyectos y equipos de trabajo.

Otro ejemplo representativo es Github, hoy en día una de las piedras angulares del desarrollo de Open Source. Github se describe a así mismo como la red social de los desarrolladores de software.

Siguiendo con las aplicaciones y servicios para desarrolladores, otro ejemplo de empresas que usan Ruby on Rails es Heroku. Un servicio de hosting en la nube totalmente automático. Nació precisamente para aplicaciones de Ruby y posteriormente agrego soporte a otros lenguajes/frameworks.

Shopify es un servicio que provee de tiendas de comercio electrónico a través de las cuales es posible tener una tienda lista en cuestión de minutos. De acuerdo a Shopify su servicio es utilizado por más de 150,000 tiendas.

En la línea de comercio electrónico se encuentra también SpreeCommerce, la cual es una solución completa de comercio electrónico Open Source utilizada en miles de tiendas en todo el mundo.

500px es una aplicación para fotógrafos donde pueden presentar su trabajo, recibir retroalimentación, publicar portafolios y a través del servicio Prime vender fotografías.

Otros ejemplos más son:
- Indiegogo
- Goodreads
- Hulu
- ScribD
- CrunchBase
- Square
- AirBnB
- ThemeForest

La lista de empresas que hoy en día utilizan Ruby on Rails puede ser interminable, los ejemplos antes mencionados son sólo una muestra de quienes utilizan esta marco de trabajo desde hace ya varios años en negocios exitosos.

Nuestra primera aplicación de Ruby on Rails.

El primer paso para poder iniciar a desarrollar aplicaciones en Ruby on Rails es tener instalado Ruby en nuestro equipo de cómputo. Ya vimos en el capítulo anterior cómo realizar una instalación de Ruby.

Con Ruby instalado y listo para usar, es necesario instalar Ruby on Rails. Es muy sencillo realizar la instalación de Rails, esto gracias a la herramienta gem que existe en toda instalación de Ruby.

gem es una herramienta que hace la instalación de librerías de Ruby sea sumamente sencilla. gem utiliza directorios donde los desarrolladores registran sus librerías. El directorio más popular es Rubygems.

Para instalar Ruby on Rails es tan sencillo como ejecutar el siguiente comando:

$ gem install rails

El comando instalará la versión más reciente de Rails, que al momento de escribir éste capítulo es la versión 4.2.

Una vez que Rails está instalado en nuestro ambiente de desarrollo ha llegado el momento de crear nuestra primera aplicación de Rails.

Nuestra aplicación en éste capítulo va a ser muy sencilla. Vamos a crear una aplicación que permita a un equipo de desarrolladores registrar las respuestas de las 3 preguntas del Standup meeting de la metodología de SCRUM:
- ¿Qué hice hoy?
- ¿Qué voy a hacer mañana?
- ¿Hay algo que me impida cumplir mis objetivos?

En el caso de nuestra aplicación vamos a registrar el nombre del ingeniero que está realizando la entrada y en un área de texto la respuesta a las 3 preguntas.

Llamaremos a nuestra aplicación Standup Meeting Log.

Rails incluye un generador que permite crear toda la estructura de una aplicación de Rails de forma muy sencilla.

$ rails new standup_meeting_log

standup_meeting_log es un parámetro requerido al comando y representa al nombre de la aplicación de Rails. Es estándar que al crear una aplicación el nombre de la misma sea en minúsculas y si el nombre de conforma de más de una palabra, éstas se separan con un _.

Al finalizar la ejecución del comando tendremos un folder con el mismo nombre de nuestra aplicación y cuyo contenido es una aplicación completa de Rails, vacía, pero completa.

Anatomía de una aplicación de Rails

Una aplicación de Ruby on Rails esta compuesta de varios folders y archivos que son generados al momento de crear una nueva aplicación.

$ ls
Gemfile      Procfile     Rakefile     bin          config.ru    lib          public       tmp          Gemfile.lock README.md    app          config       db           log          test         vendor

El folder más importante es app. Éste folder contiene la estructura del código que es específico a nuestra aplicación.

Ahí podemos encontrar los Modelos, Vistas y Controladores además de recursos adicionales como Javascripts, Hojas de estilo e imágenes.

En una aplicación moderna de Rails en este folder colocaremos código que se encuentra fuera del patrón MVC pero que es necesario para nuestra aplicación.

lib es utilizado para código que no es exclusivo a nuestra aplicación y que en algún momento puede ser extraído en forma de una librería o gema como las conocemos en Ruby.

En config encontramos los archivos de configuración de Ruby on Rails así como archivos que se ejecutan al momento que nuestra aplicación inicia. Estos archivos de configuración contienen todo lo necesario para que nuestra aplicación desde el momento cero esté lista para iniciar y responder peticiones de un navegador. La configuración inicial nos permite enfocarnos en la funcionalidad de nuestra aplicación y no en configuraciones iniciales.

Todas nuestras pruebas automáticas se van a encontrar en el folder de test.

El archivo Gemfile es el manifiesto de las gemas de las cuales depende nuestra aplicación de Rails. Ahí podemos especificar nombre de las gemas y versiones específicas entre otras cosas.

Finalmente el archivo config.ru es el archivo que permite a nuestra aplicación de Rails iniciar encima de Rack. Rack es un API unificada, mínima y simple que permite la creación de aplicaciones de Ruby que requieren de gestión de HTTP.

Del resto de los folders y del contenido nos ocuparemos conforme avancemos en el contenido del libro.

Ejecutar una aplicación de Rails

El que al momento de ejecutar el generador de aplicaciones de Rails se crea una aplicación vacía, es decir no tiene ninguna lógica ni código específico de nuestras necesidades, pero si se crea la configuración inicial completa de una aplicación de Rails.

Esto nos permite ejecutar nuestra aplicación un instante después de su creación, no tenemos que realizar ni especificar ninguna configuración adicional.

Estando dentro del folder de nuestra aplicación vamos a ejecutar el servidor web de Rails con el siguiente comando:

$ rails s
=> Booting WEBrick
=> Rails 4.2.0 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
[2015-02-16 09:56:50] INFO  WEBrick 1.3.1
[2015-02-16 09:56:50] INFO  ruby 2.2.0 (2014-12-25) [x86_64-darwin14]
[2015-02-16 09:56:50] INFO  WEBrick::HTTPServer#start: pid=2715 port=3000

Del resultado de ejecutar el comando rails s podemos ver que nuestra aplicación ha sido lanzada en el servidor web WEBrick y que está disponible en el puerto 3000 de localhost. Al abrir nuestro navegador en http://localhost:3000 debemos de ver la siguiente pantalla.

Welcome Screen

Es importante resaltar que el servidor WEBrick es y debe ser utilizado únicamente para desarrollo, pero nunca para ejecutar aplicaciones de Rails en producción. Más adelante veremos como podemos cambiar a otro servidor web en nuestra aplicación.

Para detener al servidor web solamente hay que presionar Ctrl-C.

Los ambientes de ejecución de Rails

Cuando ejecutamos nuestra aplicación vacía en la sección anterior, la segunda línea de la respuesta de ejecutar rails s nos indica que nuestra aplicación esta iniciando en modo de development o desarrollo.

En Rails tenemos por omisión 3 ambientes de ejecución: desarrollo, pruebas y producción. La gran diferencia entre los 3 ambientes es la configuración inicial de nuestra aplicación.

Para nuestro caso en este momento con saber que estamos ejecutando nuestra aplicación en modo de desarrollo es suficiente.

Uso de scaffolding

Para iniciar con el desarrollo de ésta aplicación de demo utilizaremos uno de los generadores de Rails llamada scaffold, el cual nos da un punto de partida con los 3 elementos básicos de los patrones de Rails: modelo, controlador y vista.

El scaffold de igual forma generará otros artefactos como rutas y migraciones necesarias para una aplicación de Rails.

Para ejecutar el generador, desde el folder de nuestra aplicación ejecutamos:

$ bin/rails g scaffold entry name:string notes:text

La respuesta de este comando nos hace ver que creo de forma automática una serie de archivos para nosotros. Pero vamos primero a analizar el comando que acabamos de ejecutar.

bin/rails g es la forma de indicarle a Rails que queremos hacer uso de uno de los generadores disponibles por omisión en Rails, si queremos ver la lista de los generadores solamente ejecutamos:

$ bin/rails g

scaffold es el nombre del generador que deseamos utilizar y el resto de los valores son sus parámetros. entry representa el nombre del recurso que deseamos generar, para nuestro ejemplo es una entrada a la bitácora de las Standup Meetings. name y notes son los atributos de cada entrada. string y text representan los tipos de datos que name y notes respectivamente van a guardar.

Vamos analizando más a detalle los archivos generados por el comando.

Migraciones
Una migración en Rails la podemos ver como un mecanismo para controlar las versiones de cambios en el esquema de nuestra base de datos. Es decir cada cambio en la estructura de la base de datos va a acompañado de un numero de versión que nos permite saber la secuencia de como se tienen que aplicar los cambios en order.

Además Rails mantiene en la base de datos el numero de la última version aplicada de forma que es imposible aplicar el cambio en mas de una ocasión de forma accidental. Este mecanismo nos permite la recreación de bases de datos de una manera simple.

En nuestro caso el archivo db/migrate/20150216172244_create_entries.rb fue generado.

Simplemente con el nombre del archivo podemos empezar a ver ciertos puntos interesantes. El primero, es que el archivo tiene como parte del nombre un timestamp es decir tiene la fecha y hora de creación, esto es lo que nos ayuda versionar y a Rails a entender el orden en que una serie de migraciones deben de ser aplicadas.

El segundo punto es que como parte del nombre dice entries y no entry como especificamos con el comando scaffold. Veremos que Rails hace uso de la pluralización de palabras para definir los nombres de forma automática para ciertos elementos de la aplicación. A esto lo conocemos como Convención sobre Configuración. El cambio en el nombre indica que Rails va a crear una tabla entries para guardar la información.

Si abrimos el archivo nos encontramos con lo siguiente:

class CreateEntries < ActiveRecord::Migration
  def change
    create_table :entries do |t|
      t.string :name
      t.text :notes

      t.timestamps null: false
    end
  end
end

Confirmamos que el nombre de la tabla es entries y que tiene 2 columnas, name y notes. También podemos apreciar que la sintaxis es una sintaxis especial de Rails y no son comandos de SQL. Es una sintaxis agnóstica al motor de la base de datos, esto permite técnicamente el poder reemplazar un motor de base de datos por otro bajo ciertas circunstancias.

Para aplicar la migración a la base de datos ejecutamos el siguiente comando:

$ rake db:migrate

El resultado de ésta operación nos indica que la tabla entries fue creada, pero demos un paso atrás, nunca especificamos el motor de base de datos, ¿Cómo es esto posible?.

Al momento de que creamos nuestra aplicación, no especificamos motor de base de datos, por este motivo Rails tomó la decision de utilizar sqlite, un motor super ligero, autónomo y muy sencillo de utilizar. Esto lo podemos confirmar si abrimos el archivo config/database.yml

Por el momento no hay que preocuparnos por el motor de base de datos, cuando avancemos en los capítulos veremos como podemos cambiar el motor de base de datos.

Una vez ejecutada nuestra migración, se crea un nuevo archivo db/schema.rb. El cual se mantiene actualizado según vayamos creando más migraciones en nuestra aplicación.

Con respecto al comando rake vamos a utilizarlo muy seguido en el desarrollo de aplicaciones de Rails, por lo tanto nos estaremos familiarizando con él en el transcurso del libro.

Modelos
Otro de los archivos creados por el generador de scaffold es el modelo Entry. Este es un modelo de ActiveRecord que nos permite realizar un mareo entre una clase con atributos y una tabla con columnas. El archivo fue creado en app/models/entry.rb.

Al abrirlo nos encontramos con lo siguiente:

class Entry < ActiveRecord::Base
end

No tiene contenido. Simplemente define la clase y define que hereda de ActiveRecord::Base. Pero antes de explicar que pasa, vamos a lanzar la consola de Rails para realizar algunos experimentos.

$ rails console

Una vez dentro de la console vamos a ejecutar los siguientes comandos:

irb(main):001:0> Entry.all
  Entry Load (2.5ms)  SELECT "entries".* FROM "entries"
=> #<ActiveRecord::Relation []>
irb(main):002:0> Entry.create name: 'Pedro Páramo', notes: 'Primera entrada'
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "entries" ("name", "notes", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Pedro Páramo"], ["notes", "Primera entrada"], ["created_at", "2015-02-16 20:23:30.846879"], ["updated_at", "2015-02-16 20:23:30.846879"]]
   (1.3ms)  commit transaction
=> #<Entry id: 1, name: "Pedro Páramo", notes: "Primera entrada", created_at: "2015-02-16 20:23:30", updated_at: "2015-02-16 20:23:30">
irb(main):003:0> Entry.all
  Entry Load (0.3ms)  SELECT "entries".* FROM "entries"
=> #<ActiveRecord::Relation [#<Entry id: 1, name: "Pedro Páramo", notes: "Primera entrada", created_at: "2015-02-16 20:23:30", updated_at: "2015-02-16 20:23:30">]>
irb(main):004:0>

Entry.all realiza una consulta a la base de datos por todas las entries. Y regresa un ActiveRecord::Relation vacío.

Entry.create name: 'Pedro Páramo', notes: 'Primera entrada' crea una entry con los parámetros indicados.

Luego volvemos a ejecutar Entry.all y esta vez el objeto ActiveRecord::Relation contiene un elemento, el que creamos hace un momento.

Hagamos un par de pruebas más:

irb(main):004:0> entry = Entry.first
  Entry Load (0.3ms)  SELECT  "entries".* FROM "entries"  ORDER BY "entries"."id" ASC LIMIT 1
=> #<Entry id: 1, name: "Pedro Páramo", notes: "Primera entrada", created_at: "2015-02-16 20:23:30", updated_at: "2015-02-16 20:23:30">
irb(main):005:0> entry.name
=> "Pedro Páramo"
irb(main):006:0> entry.notes
=> "Primera entrada"

Ahora realizamos una consulta por el primer entry en la base de datos y lo asignamos a una variable. Después desplegamos el valor de los atributos name y notes.

Todo esto sin que la definición de la clase Entry tenga más código que simplemente indicar que hereda de ActiveRecord::Base.

Y es precisamente esta herencia la que nos permite realizar consultas a la base de datos, crear registros y consultar el valor de los atributos.

Rutas y URLs
El generador scaffold también modifico el archivo config/routes.rb, agregando al inicio del mismo la siguiente línea:

resources :entries

El efecto que este cambio tiene lo podemos ver con uno de los comandos de rake.

$ rake routes

El cuál imprime una tabla como la siguiente:

    Prefix Verb   URI Pattern                 Controller#Action
   entries GET    /entries(.:format)          entries#index
           POST   /entries(.:format)          entries#create
 new_entry GET    /entries/new(.:format)      entries#new
edit_entry GET    /entries/:id/edit(.:format) entries#edit
     entry GET    /entries/:id(.:format)      entries#show
           PATCH  /entries/:id(.:format)      entries#update
           PUT    /entries/:id(.:format)      entries#update
           DELETE /entries/:id(.:format)      entries#destroy

O si ejecutamos nuestro servidor de Rails y navegamos a http://localhost:3000/rails/info/routes podemos ver la misma información.

Rails Routes

Vamos a enfocarnos en las columnas Verb, URI Pattern y Controller#Action.

URI Pattern nos indica que URL ofrece nuestra aplicación de Rails para navegar la información, en el caso de /entries nos dice que podemos navegar a http://localhost:3000/entries. Sin embargo el patrón de /entries aparece duplicado, pero si vemos la columna de Verb observamos que para uno el verbo es GET y para el otro es POST.

Para entender que pasa aquí, es necesario conocer los verbos que forman parte del estándar de Hypertext transfer protocol los cuales dictan desde el navegador web la forma en como queremos acceder a un recurso, en este caso entry.

Para GET le indicamos al servidor web que queremos consultar información de ese recurso. En el caso de POST le indicamos al servidor web que deseamos crear un recurso de tipo entry y que le estamos enviando todos los parámetros necesarios.

Adicionalmente si observamos la columna Controller#Action veremos que cada par de patrón/verbo están relacionados con una acción en un controlador. En nuestro caso la relación va con el controlador Entries y las acciones index y create respectivamente.

Es necesario detenernos un momento y darnos cuenta que los nombres tienen gran relevancia en Rails. Tenemos un modelo llamado entry que hace uso de una tabla entries y que las URLs para acceder a la información del mismo apuntan a /entries y un controlador Entries responde para cada URL definida.

Nada de esto es una casualidad, es parte de como Rails está diseñado y de como todas las piezas que conforman una aplicación de Rails se conectan entre sí.

Controladores y vistas
Ahora que entendemos que en cada URL de nuestra aplicación existe un controlador que responde con una acción, vamos a examinar el controlador generado por el generador scaffold.

El controlador lo encontramos en el archivo app/controllers/entries_controller.rb al abrirlo, lo primero que notamos es que hay 6 métodos definidos en la parte pública de la clase - los métodos definidos antes de la palabra clave private -.

class EntriesController < ApplicationController
  before_action :set_entry, only: [:show, :edit, :update, :destroy]

  # GET /entries
  # GET /entries.json
  def index
    @entries = Entry.all
  end

  # GET /entries/1
  # GET /entries/1.json
  def show
  end

  # GET /entries/new
  def new
    @entry = Entry.new
  end

  # GET /entries/1/edit
  def edit
  end

  # POST /entries
  # POST /entries.json
  def create
    @entry = Entry.new(entry_params)

    respond_to do |format|
      if @entry.save
        format.html { redirect_to @entry, notice: 'Entry was successfully created.' }
        format.json { render :show, status: :created, location: @entry }
      else
        format.html { render :new }
        format.json { render json: @entry.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /entries/1
  # PATCH/PUT /entries/1.json
  def update
    respond_to do |format|
      if @entry.update(entry_params)
        format.html { redirect_to @entry, notice: 'Entry was successfully updated.' }
        format.json { render :show, status: :ok, location: @entry }
      else
        format.html { render :edit }
        format.json { render json: @entry.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /entries/1
  # DELETE /entries/1.json
  def destroy
    @entry.destroy
    respond_to do |format|
      format.html { redirect_to entries_url, notice: 'Entry was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_entry
      @entry = Entry.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def entry_params
      params.require(:entry).permit(:name, :notes)
    end
end

Estos métodos son: index, show, new, edit, create, update y destroy. Cada método se mapea a una acción definidas en las rutas. De hecho y en forma de documentación en la definición de cada método existe un comentario que muestra como debe de ser la URL con la cual se accede a tal acción.

Cada acción tiene un propósito general y una o más posibles respuestas estándar. Las cuales obviamente se ajustan a las necesidades de nuestra aplicación.

Finalmente nos queda conocer un poco sobre las vistas y el papel que juegan en una aplicación de Rails. Como ya se mencionó anteriormente, las vistas se encuentran en el folder app/views/<nombre del controlador>, en el caso de nuestro ejemplo encontraremos 4 vistas para EntriesController: index, show, new y edit.
Cada una lleva el nombre de la acción primaria donde es utilizada en el controlador.

Las vistas llevan una extensión muy peculiar: .html.erb. Esto indica que las vistas son archivos de html y la parte erb hace notar que tienen incrustado código de Ruby, el cual es interpretado antes de enviar la respuesta final en puro html al navegador.

Veamos el ejemplo de la vista index.html.erb.

<p id="notice"><%= notice %></p>

<h1>Listing Entries</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Notes</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @entries.each do |entry| %>
      <tr>
        <td><%= entry.name %></td>
        <td><%= entry.notes %></td>
        <td><%= link_to 'Show', entry %></td>
        <td><%= link_to 'Edit', edit_entry_path(entry) %></td>
        <td><%= link_to 'Destroy', entry, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Entry', new_entry_path %>

Vamos a encontrar secciones delimitadas por <% %>, el código dentro de estos indicadores es código de Ruby. También hay que notar que el controlador en la acción index define una variable de clase @entries y que esta variable está disponible para la vista de forma automática.

Otro elemento que nos vamos a encontrar en una vista son los helpers, los cuales sólo están disponibles en el contexto de las vista y que ayudan a la generación de código html, como por ejemplo link_to que sirve para crear links.

Si vemos el caso de las vistas new y edit notaremos que de contenido solo tienen código de Ruby con una llamada al helper render y como parámetro tiene form. En este caso render nos permite realizar una llamada a una vista parcial. Una vista parcial es un fragmento que por sí sólo no representa la respuesta de una acción de un controlador, pero que puede ser código que se puede reutilizar e incrustar en otras vistas.

Vista new.html.erb

<h1>New Entry</h1>

<%= render 'form' %>

<%= link_to 'Back', entries_path %>

Vista _form.html.erb

<%= form_for(@entry) do |f| %>
  <% if @entry.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@entry.errors.count, "error") %> prohibited this entry from being saved:</h2>

      <ul>
      <% @entry.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :notes %><br>
    <%= f.text_area :notes %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Ejecutando nuestra aplicación

Ya que conocimos un poco más del código que se genera con el uso de scaffold es tiempo de ejecutar nuestra aplicación y ver el resultado de nuestro arduo trabajo.

$ bin/rails s

Apuntamos nuestro navegador a http://localhost:3000/entries y veremos que tenemos una solución completa para ver, crear, editar y eliminar - CRUD - registros de tipo Entry.

Aplicación de ejemplo

Obviamente nuestra aplicación no es muy atractiva visualmente y hay varias cosas que aun podemos mejorar, pero si tomamos en cuenta que con un par de comandos llegamos a este punto no suena nada mal.

Conclusiones

Durante éste capítulo conocimos un poco de la historia y los principios que hay detrás de Ruby on Rails. De igual forma tuvimos la oportunidad de crear una aplicación muy simple en cuestión de minutos, lo que nos permite darnos una pequeña idea de la mejora en productividad que nos ofrece un marco de trabajo como Rails.

La idea detrás del capítulo es simplemente familiarizarnos un poco con el marco de trabajo, ya que en los capítulos siguiente estaremos trabajando en una aplicación más grande en donde vamos a ver una serie de aspectos más avanzados en el desarrollo de aplicaciones Web.

La información de ayuda sobre Rails la podemos encontrar en muchos sitios en Internet, pero hay 3 recursos mínimos que son indispensables para cualquier desarrollador.

El resto del capítulo está disponible en el libro en formatos para Kindle, ePub y PDF.

Comprar el libro

Aprendiendo Ruby on Rails 4.0

Mario Alberto Chávez Cárdenas

Copyright (C) 2013 Mario Alberto Chávez Cárdenas.