Ruby

Ruby es un lenguaje de programación orientado a objetos (a modo de “script”) enfocado en la Web que en la primera decada del siglo 21 se popularizó con acogida en pequeñas empresas que van surgiendo (startups). Creado como “open source” por Yukihiro Matsumoto, se promociona como el mejor amigo del programador enfocándose en la simplicidad y productividad. Sus conceptos no suelen ser tan sencillos dada la diferencia con otros lenguajes, sin embargo, una vez asimilados estos conceptos la productividad se hace notar. Es decir, aunque su curva de aprendizaje no sea ágil para empezar los beneficios son mayores. Por otra parte, después de PHP, Ruby es un lenguaje que puedes encontrar en el servicio esencial de hospedaje web (web-hosting), es decir, que puede funcionar con poca inversión.

Actualmente, es posible correr Ruby bajo la máquina virtual Java (JVM) por medio de la tecnología JRuby o directamente con GraalVM.

Esta es una referencia ágil para quién tenga nociones de programación o codifique con algún otro lenguaje, también a modo de repaso y uso frecuente. Siendo así, tener esta información como memoria te resultará simple de acceder a los fundamentos, incluso como prueba de concepto sobre el lenguaje.

Tips esenciales del lenguaje

Para quien tenga habilidades, experticia en programación y/o requiera agilidad en conceptos técnicos, pueden resumirse los siguientes tips esenciales del lenguaje:

  1. Los tipos de datos son genéricos y no se indican pero se identifican por el contenido de la variable (integer, float, string, array, hash). Las variables se definen simplemente con la asignación del valor. Se usa nil para nulos.
  2. Las funciones se definen con def, luego los parámetros van entre paréntesis (...), continuando con el nombre del parámetro, el caracter : que separa el tipo de datos posteriormente (y separando los parámetros con coma ,).
  3. Para el bloque de la función o el flujo de control se finaliza con end. No aplican los corchetes de otros lenguajes ni el punto y coma.
  4. El flujo de control varía respecto a lenguajes como C, Java, Javascript, Kotlin, pero encuentras una forma equivalente para el uso de if y while, incluso para el manejo de excepciones (begin ... rescue ... end).
  5. El constructor de una clase lleva el nombre initialize y la clase se define con la palabra reservada class y el nombre que debe iniciar en mayúscula.

Ejemplo esencial

class Test
  def say
    puts "Hi there!"
  end
end

puts imprime algo en la salida de consola (pantalla)

Declaración de variables

Las variables se definen simplemente con la asignación del valor y su tipo se identifica por el contenido (integer, float, string, array, hash). De este modo, si la expresión va entre comillas (") es una cadena (string), si es un número con punto decimal es un flotante (float) sino entero (integer).

Ejemplo:

variable = "Ana"
n = 5

Definición de funciones

def plus1 (a, b)
    a + b
end

Comentarios

# Esto es un comentario de fin de línea

Condicionamiento if / else (if)

if i == 1
    puts "one"
elsif i == 2
    puts "two"
else
    puts "aha"
end

Ciclos

i = 0
while i < 10 do
    i += 1
end

Mientras encuentras que for se usa para rangos, existe la variación con until (y la condición), así como también podría plantearse un ciclo usando el método times así:

i = 0
10.times do
    i += 1
    puts i
end

Puede interrumpirse un ciclo con la sentencia break o dar el paso a la siguiente iteración con la setencia next.

Iterador (each)

collection = [1,2,3]
collection.each do |it|
    puts it
end

Las colecciones pueden ser array (vector) o hash (tupla), usan el método each y lo que va entre pipes (|it|) es la variable interna para acceder a cada instancia.

Evaluador (case … when)

result = case i
    when 1 then puts "one"
    when 2 then puts "two"
    else "aha"
end

puts result

Excepciones

begin
    ...
rescue
    puts "error"
end

Clases

class Circle {
    def initialize (radius)
        @radius = radius
    end

    def print
        puts @radious
    end
end

initialize es la funcion que opera como constructor de la clase.

Plantillas Web con Ruby (ERB)

Semejante a otros lenguajes en los que se usan plantillas web para la vista, como el caso de JSP o PHP, Ruby utiliza plantillas con extension .erb (Embbedded Ruby) que se orienta a HTML con comandos de escape para incrustar codigo haciendo uso por ejemplo de la etiqueta <%= ... %> o <% ... %> (los puntos corresponderian a codigo escrito en Ruby). La primera expresion se usa para mostrar el valor de una variable, mientras la segunda para usar sentencias tales como if o for. Veamos el ejemplo:

My city is <%= @city %>

<% for  @row in @list %>
  <%= @row %>
<% end  %>

Ademas de <%= ... %> y <% ... %>, se puede usar comentarios con la etiqueta <%# ... %> (los puntos corresponderian al comentario). De modo opcional, ERB incorpora metodos que aplican una transformacion combinandolos con <%= ... %>.

Si se desea colocar la plantilla dentro del codigo de un programa en Ruby en lugar de un archivo .erb separado, se usa %{ ... } (los puntos corresponderian a la plantilla). Veamos el ejemplo:

def get_template()
  %{
      My city is <%= @city %>

      <% for  @row in @list %>
        <%= @row %>
      <% end  %>
  }
end

Instalación de Ruby

En Windows es tan sencillo como descargar el instalador RubyInstaller, sigues los pasos y eso es todo lo que necesitarias. Veamos los comandos de instalacion para Linux Debian.

sudo apt update
sudo apt install -y ruby-full

Ruby trae el gestor de paquetes gem y con este se pueden instalar modulos y librerias como rails (Ruby on Rails - RoR) de la siguiente manera:

sudo gem install rails

Puedes verificar la version instalada respectivamente de la siguiente manera:

ruby -v
rails -v

Ademas preparamos el entorno de desarrollo gestionando el codigo en Javascript con yarn, y disponiendo de una base de datos, por ejemplo sqlite, así:

sudo apt install libsqlite3-dev
sudo gem install sqlite3
sudo npm install -g yarn

En el caso de yarn debe haberse instalado el entorno Node.js.
Los comandos sudo apt son propios del sistema Linux Debian/Ubuntu, mientras que otros como gem son del entorno sin importar el sistema (incluso Windows).
Para la instalación de sqlite3 en Windows puede consultarse en Internet.

Proyecto de inicio rapido

Para crear un nuevo proyecto con Rails te ubicas desde la linea de comandos en una carpeta que usas como espacio de trabajo y luego ejecutas por ejemplo:

rails new blog

blog seria el nombre de un proyecto nuevo. Si se reporta algún problema se revisa y ejecutas luego el comando bundle install (dentro de la carpeta del proyecto). Puedes agregar integracion con webpack ejecutando bundle exec rails webpacker:install (dentro de la carpeta del proyecto).

Al crear el proeyecto este queda operativo y se puede lanzar asi:

cd blog
rails server

Puedes revisar que muestra en un navegador reportando la dirección: localhost:3000

El siguiente proyecto

Ahora haremos un ejercicio sobre una API con Ruby on Rails. Para ello nos ubicamos en una carpeta de trabajo y ejecutamos el siguiente comando:

rails new myapi --api

El nombre del proyecto myapi puedes cambiarlo a tu gusto antes de presionar la tecla ENTER. El parámetro --api es el que indica que se creará un proyecto con plantilla para una API.

Podemos revisar y encontrar que se ha generado el archivo app/controllers/application_controller.rb con el siguiente contenido:

class ApplicationController < ActionController::API
end

Ahora generamos un modelo ejecutando lo siguiente:

cd myapi
rails g scaffold Member name:string

Esto nos debe haber generado un par de archivos, por ejemplo, para el modelo encontramos app/models/member.rb con el siguiente contenido:

class Member < ApplicationRecord
end

Y un controlador en app/controllers/members_controller.rb con el siguiente contenido:

class MembersController < ApplicationController
  before_action :set_member, only: [:show, :update, :destroy]

  # GET /members
  def index
    @members = Member.all

    render json: @members
  end

  # GET /members/1
  def show
    render json: @member
  end

  # POST /members
  def create
    @member = Member.new(member_params)

    if @member.save
      render json: @member, status: :created, location: @member
    else
      render json: @member.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /members/1
  def update
    if @member.update(member_params)
      render json: @member
    else
      render json: @member.errors, status: :unprocessable_entity
    end
  end

  # DELETE /members/1
  def destroy
    @member.destroy
  end

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

    # Only allow a list of trusted parameters through.
    def member_params
      params.require(:member).permit(:name)
    end
end

Además, se ha modificado el archivo de rutas app/config/routes.rb y obtenemos ahora el siguiente contenido:

Rails.application.routes.draw do
  resources :members
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

Ahora ejecutamos la migración, que aplica el modelo a la base de datos, y iniciamos el servicio, para esto ejecutamos los siguientes comandos:

rake db:migrate
rails s

Recuerda que cuando se ejecuta rails s (o rails server) podemos abrir el navegador y consultar la dirección: localhost:3000
Para consultar las rutas se usa rake routes, pero también podemos deducir alguna e ir directo a la dirección: localhost:3000/members

Podemos ingresar un registro desde la línea de comandos usando curl (que lo traen los sistemas tipo Linux o POSIX y es util para interactuar con el protocolo HTTP y API’s):

curl -i -H "Content-Type:application/json" -X POST http://localhost:3000/members -d '{"name":"John"}'

Si consultas en el navegador localhost:3000/members ahora debe aparecer un nuevo registro.

Programando un Servidor Web con Sinatra

Como alternativa RubyOnRails encontramas Sinatra, veamos el ejemplo esencial de su sencilla propuesta. Primero instalamos la gema respectiva así:

sudo gem install sinatra

Y el código de nuestro programa tendrá el siguiente contenido

require 'sinatra'

get '/' do
  "Hi there!"
end

Puedes revisar en un navegador consultando la dirección: localhost:4567


© 2021 by César Arcila