Aprendiendo Ruby y Rails. Parte 1. Introducción a Ruby

El presente artículo es el primero de una serie que tiene la intención de introducir los principales elementos del lenguaje de programación Ruby y del framework Ruby on Rails. En esta primera parte se explican los elementos básicos del lenguaje, de forma que posteriormente se pueda comprender y explotar a Rails como plataforma arquitectónica de desarrollo.

Antecedentes
Ruby es un lenguaje ROO (Radical Object Oriented Language) a diferencia de otros lenguajes con un perfil de objetos como C# y Java que son menos Orientados a Objetos en su sintáxis y semántica.

Ruby fue creado en Japón por Matz (aka. Yukihiro Matsumoto) en 1995 y se empezó a utilizar en el hemisferio occidental a partir del año 2000. Es un lenguaje que desde sus inicios fue diseñado para ser simple, elegante, funcional, fácil de emplear, confortable y que brinde libertad al programador, y desde su diseño toma elementos de otros lenguajes tales como: Perl, Python, Java y SmallTalk.

Entre las principales características de Ruby podemos citar:
• Lenguaje de Scripting.
• Radicalmente Orientado a Objetos.
• De tipos dinámicos.
• Funcional.
• Altamente reflexivo.
• Permite la creación de lenguajes de dominio específico.

Debido a lo anterior Ruby:
• Es fácil de escribir.
• Típicamente es interpretado.
• Favorece el desarrollo rápido sobre ejecución rápida (en gran medida debido a la facilidad que permita la utilización de tipos dínámicos).
• Permite la integración e interface con componentes escritos en otros lenguajes.

Uno puede encontrar intepretes de Ruby en prácticamente cualquier plataforma, siendo las más populares las derivadas de Linux en cualquiera de sus sabores: Fedora, RedHat, Ubuntu, Debian, etc. e incluso en MacOS X (Tiger) y Windows XP/2000.

Conceptos Básicos del Lenguaje
Como ya se había mencionado en un principo, Ruby es un lenguaje radicalmente Orientado a Objetos, esto es, su sintaxis y semántica presentan que en su mayoría todos los tipos son objetos, de hecho muchos operadores son métodos de los objetos. A continuación se explicarán los elementos principales.

Comentarios
En Ruby hay dos formas de definir comentarios dentro del código.

La primera es cuando el comentario sólo abarca una línea o parte de una línea. Para este caso se utiliza el carácter de gato ( # ) y después se agrega el comentario.

Por ejemplo:

#--- Esto es un comentario que abarca toda una línea
variable = objeto.metodo(parametro) # Este es otro comentario!!!
# y este es otro mas!!!

La segunda es cuando el comentario abarca un bloque de líneas. Para este caso se utiliza el bloque =begin =end

Por ejemplo:

...
=begin
Aún no se decide si Pedro tendra a su cargo 2 o 4 personas.
El metodo podrìa invocarse de esta forma:
objEmpleado.setSubordinados( “Emp23”, “Emp24”)
o de esta otra:
objEmpleado.setSubordinados( “Emp23”, “Emp24”, “Emp32”, “Emp34” )
=end
...

En este ejemplo Ruby toma como comentarios todas las líneas que se encuentran situadas en medio del bloque =begin =end.

NOTAS:
• En este momento la versión actual del intérprete de Ruby (1.8.5) no permite hacer comentario embebidos.
• Tanto =begin como =end deben de aparecer al inicio de linea. Clases
La sintaxis para definir en Ruby una clase es similar a lo que pasa en C++, Java y C#:

class NombreDeLaClase
end

Igualmente las reglas que aplican para definir el nombre de una clase son similares a lo que acontece en Java y C#, cualquier sucesión alfanumérica con mayúsculas o minúsculas incluyendo el guión bajo, siempre que el nombre inicie con un carácter alfabético (no numérico).

Métodos
La sintáxis para definir en Ruby el método de una clase es:

def nombreDelMetodo( param1, param2, … paramN )
return( valor ) #--- Ojo! usar return es opcional
end

Si el método pertenece a una clase este debe ser declarado dentro del cuerpo de la clase, por otra parte, las reglas que aplican para definir el nombre de un método son similares a lo que acontece en Java y C#, alfanumérica con mayúsculas o minúsculas incluyendo el guión bajo, siempre que el nombre inicie con un carácter alfabético (no numérico).

Los parámetros son opcionales y se diferencian uno de otro mediante comas, cuando no se desea incluir ningun parámetro es opcional incorporar o no los paréntesis que rodean a los parámetros.<

Tres puntos importantes a remarcar respecto a los métodos:
• A diferencia de lo que acontece en lenguajes como Java y C#, en Ruby un método puede o no ser parte de una clase. En este sentido, un método se puede comportar más como una función de C/C++ o JavaScript, ya que puede ser declarado en cualquier lugar del archivo o proyecto.
• Los tipos de los parámetros no requieren ser declarados. Esto se debe a que Ruby es un lenguaje dinámico, el intérprete resuelve en tiempo de ejecución la relación correcta de los tipos que son pasados como parámetros a un método.
• Los métodos siempre devuelven un valor por default, el valor puede ser regresado mediante la cláusula return, o si ésta no es incoporada el método devolverá la última expresión evaluada.

Constructores
De igual manera que en C++, Java y C# Ruby tiene un método especial que permite la construcción de un objeto en tiempo de ejecución (constructor). Sin embargo a diferencia de otros lenguajes, en Ruby la sintaxis de constructor NO sigue las convenciones de nombrado del constructor. Esto es, no se llama igual que el nombre de la clase.

La sintaxis es:

def initialize( param1, param1, param3 )
end

initialize sigue el resto de las convenciones respecto a parámetros y valor de retorno que cualquier otro tipo de método.

Variables de Instancia y Atributos
En Ruby una variable de instancia es similar a lo que en C++, Java y UML se conoce como atributo y a lo que en C# se le denomina campo (field). Esto es es una propiedad o parte de la clase que puede representar un valor específico o un objeto completo.

Una variable de instancia se declara de la siguiente manera:

@variableDeInstancia = valor

En Ruby, un atributo se refiere a un método que tiene el mismo nombre de una variable de instancia y que sirve para modificar el valor de dicha variable.

Por ejemplo, supongamos que tenemos el siguiente código:

class CEmpleado
#...
def sueldo( sueldoAsignado )
@sueldo = sueldoAsignado
end
end

Aquí el método sueldo coincide con la varible de instancia @sueldo, y además estamos empleando este método para asignarle un valor específico a la variable de instancia. Esta construcción nos permitirá hacer realizar declaraciones como la siguiente:

objEmpleado.sueldo( 100000 )

Una vez entendido el concepto de atributo, comparémoslo con el concepto de atributo en C#, en el cual un atributo es un tipo de anotaciones de código (metadatos) que puede ser aplicado a un tipo (clase, interface, estructura, etc.), miembro (propiedad, método, etc.), assembly o módulo… Ambos conceptos son bastante diferentes ¿verdad? Es por eso que debemos poner atención cuando nos referimos a atributos en Ruby.

Idiomas comunes
Analicemos el siguiente código para una clase que represente a un usuario.

class CUsuario
attr_accessor :nombre, :password, :permisos
attr_accessor :IDUsuario

def initialize( nombre, password, permisos )
@nombre = nombre
@password = password
@permisos = permisos
end

def nombre=( nombre )
@nombre = nombre
return( true )
end

def password=( password )
@password = password
return( true )
end

def permisos=( permisos )
@permisos = permisos return( true ) end

end

Si se dan cuenta, en este caso no declaramos atributos. En lugar de eso empleamos el idioma común attr_accessor que en conjunción con los símbolos :nombre, :password, :permisos y los atributos nombre=, password=, permisos= permitirán lograr el mismo efecto y obtener mayores beneficios. Veamos con más calma a que nos referimos con todo esto.

Empecemos con el elemento attr_accesor, el cual a todas luces pareciera ser un keyword. En realidad este elemento es lo que se conoce como un idioma común en Ruby.

Un idioma común es cuando existen construcciones que se repiten continuamente durante el desarrollo de programas. Cuando esto pasa, los equipos de mantenimiento de compiladores, intérpretes, frameworks y librerías de uso común de los lenguajes generan estructuras o elementos que declarativamente son “atajos” y que tienen la intensión de reducir la cantidad de código y/o hacerlos más legibles.

En el caso de Ruby el equipo de mantenimiento de las librerías se percató de esta situación y creó una serie de idiomas que reducen la cantidad de código a escribir (aún cuando en realidad en tiempo de ejecución estos idiomas se desglosan en otras estructuras o declaraciones más grandes o complejas). Los siguientes son los idiomas más comúnes para los atributos en Ruby:

attr_reader :metodo #--- solo lectura
attr_writer :metodo #--- solo escritura
attr_accessor :metodo #--- lectura y escritura

Para comprender mejor como funcionan estos idiomas mostraremos un ejemplo. Supongamos que declaramos

attr_accessor :direccion

Este idioma tiene el mismo efecto que si declararamos

def direccion
@direccion
end
def direccion=( direccion )
@direccion = direccion
end

En este caso, el primer método sirve como un “getter” de la variable de instancia. Es decir, permite colocar a la variable como un RValue a través de una sentencia como:

unaDireccion = objeto1.direccion

El segundo método sirve como un “setter” de la variable de instancia. Es decir, permite colocar a la variable como un LValue dentro de una sentencia:

#...
#...
Objeto1.direccion = otraDireccion
# O
Objeto1.direccion = objeto2.otraDireccion

A este último tipo de método se le conoce como atributo escribible (Writable Attribute) porque permite “escribir” el valor de una variable de instancia utilizando un método del tipo atributo.

Antes de finalizar con esta sección es importante remarcar que cuando utilizamos este tipo de idiomas comunes debemos incorporar también el nombre del método que tratamos de definir como getter o setter (y que además coincide con el nombre de la variable de instancia). En nuestro caso, dichos métodos fueron: :nombre, :password, :permisos y :IDUsuario. La razón por la que llevan dos puntos se explica a continuación.

Symbols
Cuando utilizamos los 2 puntos antes de un identificador ( : ), en realidad lo que estamos definiendo es un alias para identificar cosas. Este tipo de alias se le conoce como símbolo (o Symbol en Inglés) y es muy utilizado en Ruby y Rails para identificar o nombrar a otros elementos.

Algunos ejemplos son:

#--- nombrado de relaciones
has_many :clientes
#--- identificar parametros nombrados
Cliente.find( :all )
#--- como parametros keyword
Cliente.find( :all, :limit =>5, :order=>”nombre” )

Herencia
En Ruby al igual que en otros lenguajes como C++, Java y C# es posible definir relaciones de generalización (o especialización según el punto de vista) en donde una clase puede tener una o más hijas y así conformar toda una jerarquía.

La sintaxis para declarar que una clase deriva (hereda) de otra es:

class NombreClaseHija < NombreClasePadre
#...
end

Por ejemplo, si queremos crear una clase para representar aun administrador de sistema, la cual herede de nuestra clase de usuario, lo haríamos con código como el siguiente:

class CAdminSistema < CUsuario
def initialize(nombre, password, permisos )
super( nombre, password, permisos )
end def cambiaPermisos( permisos )
super.permisos=permisos
end end

Podemos apreciar que dentro del código se tiene la declaración:

super( nombre, password, permisos )

super es una palabra reservada que invoca al método asociado en la clase padre. En nuestro caso, como super estaba incorporada dentro del método initialize, en realidad adentro de éste se está invocando al método initialize de la clase padre (CUsuario.initialize).

Resumen
A lo largo de este tutorial iniciamos la revisión de diferentes características de Ruby y las herramientas básicas para iniciar la programación con el lenguaje, así mismo analizamos brevemente algunas particularidades que lo hace diferente respecto a otros lenguajes como C++, Java y C#.

En los artículos subsecuentes abarcaremos más elementos del lenguaje como arreglos, hashes y bloques que permitirán apreciar la potencia, facilidad y elegancia de Ruby. Iniciamos con el análisis de estos elementos porque consideramos fundamental que para comprender de manera general la arquitectura de Rails y poder emplearlo como framework de desarrollo, se necesita partir de una base.

En las siguientes entregas, ejemplificaremos el uso del lenguaje a través de un caso práctico e iniciaremos con el uso de Rails.

Mientras tanto, los invito a que visiten www.ruby-lang.org y descarguen el interprete de Ruby para que puedan empezar a realizar algunos ejercicios con este fascinante lenguaje.

Referencias
• Thomas David, Fowler Chad, Hunt Andy. “Programming Ruby”. 2nd Edition. The Pragmatic Bookshelf, 2005.
• Thomas David, Heinemeier Hanson David , et al. “Agile Web Development with Rails”. 2nd Edition. The Pragmatic Bookshelf, 2006. Black, David A. “Ruby for Rails”. Manning Publications Co., 2006
• Troelsen, Andrew. “Pro C# 2005 and the .NET 2.0 Platform” 3rd Edtion. Apress, 2005.
• Lucas Carlson, Leonard Richardson. “Ruby Cookbook”. O’Reilly Media, 2006.
• www.ruby-lang.org
• www.rubyonrails.org

Acerca del autor Carlos Ortega es consultor en metodologías y prácticas ágiles (XP, TDD, Refactoring, Pair Programming, etc.), cuenta con certificaciones en RUP, OOAD, UML, etc. Es Certified ATAM Evaluator y Certified Professional Software Architect ambos avalados por el SEI. Ha colaborado en numerosos proyectos para diversas organizaciones como Banco de Mexico, Elektra, Banco Azteca, Fandelli, Oracle, IMSS, Heinson, Accenture, EDS, etc. Actualmente colabora con Software Ágil, empresa dedicada al tutelaje e implementación de metodologías ágiles (SCRUM, XP, Crystal, etc.)