Instalación de Ruby (la posta para mi)

En los últimos meses instalé Ruby en al menos 4 máquinas distintas (mi máquina personal, mi desktop del trabajo, una máquina virtual y mi build server). En todos los casos intenté seguir el mismo procedimiento, pero en todos me encontré con distintos issues, estimo que debido a que los ambientes eran levemente distintos (pero todos eran Ubuntu).

Cuando hablo de instalación de Ruby, no estoy hablando de la instalación base de ruby para hacer un «Hola  mundo», sino una instalación como para crear una aplicación «de verdad» (básicamente aplicación web, con conexión a internet, manejo de xml, pruebas y build automatizado).

Habiendo seteado el contexto paso a describir los pasos comunes que logré identificar en todas las instalación que realicé y que voy a seguir la próxima vez que tenga que preparar un ambiente.

Vamos a comenzar por instalar Ruby usando apt-get, no importa si luego queremos utilizar otra versión, yo me inclino por comenzar instalando ruby con apt-get pues eso se encargará de hacer varios seteos. Entonces abrimos una terminal y ejecutamos

sudo apt-get install ruby

Si no tenemos instalado Git aún, es un buen momento para instalarlo.

sudo apt-get install git

Luego vamos a instalar Ruby Version Manager (rvm). Esta herramienta nos va permitir instalar y administrar distintas versiones de Ruby en una misma máquina. Pero para instalar RVM primero tendremos que instalar git y curl, entonces:

sudo apt-get install curl
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bashrc

Cuando finalice la instalación de estos componentes cerramos la terminal.

Ahora instalaremos ruby 1.9.2 usando RVM, para ello abrimos una nueva terminal y ejecutamos

rvm install 1.9.2

El siguiente paso es installar RubyGem, un administrador de paquetes (que en ruby se llaman gemas). La instalación de esta herramienta consisten en descargar el paquete desde http://rubygems.org/pages/download , descomprimirlo y ejecutar setup.rb (ruby setup.rb). Con esto ya estamos en condiciones de comenzar a installar gemas, pero resulta que algunas gemas en su proceso de instalación incluyen un proceso de compilación de código C, el cual puede requerir de la existencia de ciertas librerías nativas en nuestro ambiente. Por suerte las mismas pueden instalarse fácilmente utilizando apt-get.

sudo apt-get install libmysqlclient-dev libpq-dev libsqlite3-dev zlib1g-dev libreadline5-dev libssl-dev libxml2-dev libopenssl-ruby libxslt1-dev

Ahora  si, podemos proceder a la instalación de dos gemas fundamentales: rake (ruby make) y bundler (un administrador de dependencias en un punto similar a Maven).

gem install rake
gem install bundler

Con esto estamos listos para comenzar, cuando creemos nuestras aplicaciones tendremos un archivo llamado Gemfile en el cual especificaremos las dependencias de nuestra aplicación (las gemas) y con solo ejecutar bundle install, bundler se encargará de instalar las gemas especificadas.

Espero que esto les resulte útil.

Continué con Ruby y me copé

Luego de mi comienzo en el mundo Ruby, seguí avanzando: agregué tests (utilizando rspec), medí la cobertura (con simplecov) y automaticé el build contínuo (con rake y jenkins). Ahora que tengo todo mi código cubierto por pruebas voy aplicar algunos refactorings pues no estoy muy conforme con los nombres de algunos métodos y al mismo tiempo quiero agregar algunas funcionalidades nuevas. Lo que aún me falta agregar es algo que verifique el cumplimiento de estándares de codificación.

Si bien aún soy un principiante en el mundo Ruby, puedo afirmar que hacer el setup de todo lo mencionado arriba en un proyecto Ruby, me ha resultado mucho más simple que hacerlo para un proyecto C#, a pesar de la experiencia mucho más extensa que tengo con este último.

Sobre el hosteo de aplicaciones en Heroku

Luego de estar trabajando con Heroku por un par de semanas, hoy voy a compartir algunos algunos consejos útiles.

Suele ser una buena práctica al desarrollar una aplicación, manejar distintos ambientes. En general suelen manejarse al menos 4 ambientes, puede que los nombres varíen, pero en líneas generales podríamos decir:

  1. Desarrollo, donde se desarrolla aplicación
  2. Test/integración, ambiente similar de desarrollo donde se ejecutan la pruebas
  3. Staging, ambiente de prueba lo más parecido posible al de producción donde se realizan las pruebas de aceptación (UAT)
  4. Producción, ambiente final donde correr la aplicación

Al trabajar con Heroku tendremos

  1. Desarrollo es la maquina del desarrollador
  2. Test/integración, es el build server
  3. Producción ya dijimos que seria heroku, por lo cual
  4. Staging también debería ser heroku.

Si uno está dispuesto a pagar, heroku nos permite manejar más de un ambiente en la misma aplicación, pero si pretendemos un enfoque gasolero al máximo, entonces tendremos que generar 2 aplicaciones: una representará nuestro ambiente productivo y la otra a nuestro ambiente de staging. Dado que el comportamiento de ciertos componentes puede varias dependiendo de ambiente en que se encuentre, para que nuestra aplicación Heroku de staging se comporte como tal, tendremos que setear la correspondiente variable de entorno utilizando el siguiente comando

heroku config:add RACK_ENV=staging

Esta variable tiene como valor por defecto production y por eso es que no la modificaremos para nuestra aplicación de producción.

Utilizando esta variable podremos definir distintos parametros de configuración para cada uno de nuestros ambientes.

configure :production do
  DataMapper::setup(:default, ENV['DATABASE_URL'])
  DataMapper.auto_upgrade!
end

configure :staging do
  DataMapper::setup(:default, ENV['DATABASE_URL'])
  DataMapper.auto_upgrade!
end

configure :development do
  DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/mydata.db")
  DataMapper::Model.raise_on_save_failure = true
  DataMapper.auto_upgrade!
end

configure :test do
  DataMapper.setup(:default, "sqlite::memory:")
end

Para poder desplegar nuestra aplicación a los correspondientes ambientes, tendremos que agregar los correspondientes repositorios git remotos. En general uno ya lo tendremos seguramente bajo el nombre heroku, pero para evitar confusiones lo mejor seria removerlo y volver a agregarlo con un nombre mas representativo. Para ello podemos hacer

git remote add production <git-de-la-app-heroku-de-production>
git remote add staging <git-de-la-app-heroku-de-staging>

El hecho de que el despligue a Heroku este basado en git, hace muy simple el versionado de la aplicación y la vuelta atras a una versión anterior. Pero más allá de esto hay un plugin que estoy utilizando llamado Releases. Este plugin ofrece cierta funcionalidad básica en su versión gratuita (como agregar un número amigable de versión a cada despliegue y la posibilidad de hacer un rollback del último despliegue).

Continuará…

Y un día llegué a Ruby…y publiqué una gema

Y si, después de haber trabajado con Delphi, PHP, C#, Java, C/C++, Smalltalk y Python finalmente me tocó Ruby.

Recién estoy dando mis primeros pasos, no conozco bien la sintáxis y al mismo tiempo hay ciertos idioms que me resultan incómodos, pero más allá de eso he encontrado varias similitudes con Smalltalk que me han resultado muy amistosas.

A diferencia de muchos de los que se acercan a Ruby, no he hechado manos a Rails. Mi stack de desarrollo se compone de Sinatra+Datamapper+SimpleDB+Heroku. He aquí otro punto interesante, luego de trabajar con la plataforma Azure, Heroku me pareció extremadamente simple y sólido. La experiencia de usuario es muy….¿suave?, en inglés diria smooth, con lo cual creo que suave es una traducción aceptable.

La aplicación que estoy desarrollando tenia como requerimiento funcionar con identidad federada. Si bien en Southwoks ya teniamos un gema para resolver dicha cuestión, la misma corria sobre Ruby 1.8 y la idea era que mi aplicación corriera sobre 1.9 pues tiene varias mejoras interesantes. Asi que luego de un poco de investigación y algunas pruebas de concepto logré dar con un código que permite federar mi aplicación usando tokens del tipo SWT.

Y estaba tan entusiasmado que di un paso más y empaqueté dicho código en un gema (este es el nombre que se le da a las librerias reutilizables en Ruby). La gema está disponible en RubyGems y el código fuente en GitHub.

Próximamente más sobre mis aventuras en Ruby.

Sinatra Modular Applications with Ruby 1.9

Disclaimer: what I write here is something that is working for me, but I am not an expert, so I cannot declare this to be the best solution.

I am working on a small application that I know it will grow, so the traditional Sinatra application could be a mess when I have more than 10 routes.

So the strategy I have chosen is to create a base class called BaseController inheriting from Sinatra::Application, this base clase will handle global application settings.


#./base_controller.rb
require 'sinatra/base'

class BaseController < Sinatra::Base
  get '/' do
    'Home (base controller)'
  end
end

Then, I create one controller class for each application module, each of this controllers should inherit from my BaseController.

#/controllers/module1_controller.rb
require File.join(File.dirname(__FILE__),'..', 'base_controller.rb')

class Module1Controller < BaseController
  get '/' do
    'Module 1'
  end
end

Finally, in the config.ru file I define the base routes for each controller.

# config.ru
require './base_controller.rb'
require './controllers/module1_controller.rb'

map '/' do
  run BaseController
end

map '/module1' do
  run Module1Controller
end

Note: the code snippets above assume that the base_controller.rb and config.ru files are located in the root directory while every all controller files are located under «/controllers» directory.

You can download the source code from here.

Jekyll Quickstart

Some days ago Johnny posted about Jekyll and that motivated us (Martin and me) to perform some spikes with it. So in this post I will share what I have been doing. I assume that you have already set up your Ruby environment.

Let’s start by installing jekyll:


$> sudo gem install jekyll

Very easy and straightforward.

Now create a directory for your site and create the following files/folders in it (this structure is basically what Jekyll’s documentation suggests):

  • _config.yml, this file stores the configuration data that is used by Jekyll. Most of this information can assume default values or the values can be specified as command line arguments when invoking Jekyll. I suggest specifying the destination argument, which specifies where output files will be placed.
  • index.html, this will be the landing page of your site, but in order  for this file to be processed by jekyll we need to add the following line at the top of the file. This will indicate to jekyll which layout to use in order to render the page as well as its title.

---
layout: default
title: jekyll-spike
---
  • _layout, as you may imagine this folder will contain the files that define the layout of your pages (in .net we would say the «master pages»)
  • _post, this folder is where you will place the markdown files with your posts

That is pretty much all; now you can add the classic folders for static resources like images, css, etc.

Now to generate your website, just open a terminal in the root directory of your application and call jekyll

$> jekyll

This will create a whole static site under the folder you specified as the destination in the _config.yml file. Now, every time you want to add a new post/page, just create a markdown file under the _posts folder and then execute jekyll to regenerate the site.ust ese

There is also an option in jekyll to generate the site and start a webserver to host the site all at once, just execute

$> jekyll --server

Well this is all for now. If you want, you can download a zip file with this basic structure from here.

Getting started with Ruby on Windows

The life takes us through different and mysterious ways. In this occasion that way has lead me to Ruby world.

So, here are the steps I perform to get my Ruby development environment up and running on Windows 7.

I started by downloading Ruby from http://rubyinstaller.org/. In my case and because of the context of my project I choose Ruby 1.8.7.

image

The installation was very straightforward: accept the license, ensure to check the “Add Ruby executables to your PATH” option and press install.

image

After a couple a seconds the following screen displayed telling that the installation was completed.

image

The next component to install was the DevKit, a set of tools to allow the usage of C-native features in Ruby. The installation of this component was not so straighforward, I had to follow the instructions detailed here: https://github.com/oneclick/rubyinstaller/wiki/Development-Kit.

With this, we can say that the base infrastructure is ready, but it is not enough to develop applications. We will need to install gems (this is name given to Ruby packages). To install gems we can use RubyGems package manager that comes with Ruby installation. To use it, just open a Commmand Prompt and type the command to execute. In my case case I installed some tools that I already new I wanted to use:

  • Sinatra: a DSL tools to create web applications
  • Data Mapper: a persistence framework
  • Bundler: a tool to manage application dependencies
  • Heroku gem: a package to interact with Heroku platform

To install all this gems, just execute the following script:

gem install sinatra
gem install data-mapper
gem install bundler
gem install heroku

If while installing any of these gems you get an error telling “invalid date format in specification”, you will have to go to follow these steps:

  1. Go to <ruby folder>librubygems1.8specifications.
  2. Find the file mentioned in the error and open it.
  3. Look for a line assigning a date, something like s.date = %q{2011-08-17 00:00:00.000000000Z}
  4. Modify that line and remove the time s.date = %q{2011-08-17}
  5. Save the file and you are ready.

Well folks, that’s all, you are almost ready to start working. I say almost because you may want to install an IDE. But that will be the topic of another post.

To be continue….