Mostrando entradas con la etiqueta Ruby on Rails. Mostrar todas las entradas
Mostrando entradas con la etiqueta Ruby on Rails. Mostrar todas las entradas

Configurar opciones por defecto para el comando gem

sábado, marzo 10, 2012

Cada vez que voy a instalar una gema con el comando gem uso los parámetros --no-rdoc y --no-ri para que no me genere la documentación, principalmente porque nunca la uso y además demora demasiado el tiempo de instalación de las gemas. Pero escribir esos parámetros cada vez que ejecuto el comando es fastidioso.

Afortunadamente gem busca el archivo de configuración ~/.gemrc en el directorio personal del usuario y aplica las opciones que estén definidas, así que creando ese archivo en nuestro home con la siguiente línea no tendremos que tipear las opciones nunca más:

gem: --no-rdoc --no-ri

Mostrar el log de ActiveRecord en la consola de Rails

miércoles, febrero 01, 2012

Si usualmente utilizas la consola interactiva de Ruby On Rails para realizar pruebas, correr tareas de Rake, entre otras cosas y te resultaría sumamente útil ver el log de lo que esta haciendo el ActiveRecord, entonces este tip es para ti.

Simplemente ejecuta la consola desde la carpeta raíz de tu aplicación Rails:

Para rails 3.x:
$ rails c
Para rails 2.x:
$ script/console
Y luego indícale al logger que use la salida estándar:
ActiveRecord::Base.logger = Logger.new(STDOUT)
Con eso los mensajes de log del ActiveRecord se imprimirán en la consola.

LoadError con el readline al intentar abrir una consola de Rails usando rvm

lunes, mayo 02, 2011

Si usando rvm, intentas abrir una consola de Rails (con rails c o con script/console) y te escupe un error como este:

no such file to load -- readline (LoadError)

Entonces sigue estos pasos y resolverás el problema.

Primero, debemos instalar el paquete del readline en rvm (y no en el Sistema Operativo). Para eso removemos la versión actual de Ruby que podamos tener:

$ rvm remove 1.8.7

Instalamos el paquete readline:

$ rvm install package

E instalamos Ruby pero indicándole la ubicación del paquete readline:

$ rvm install 1.8.7 --with-readline-dir=$rvm_path/usr

Acto seguido, entramos a la carpeta en donde rvm almacena los fuentes de las extensiones de Ruby, específicamente del readline. En mi caso:

$ cd ~/.rvm/src/ruby-1.8.7-p302/ext/readline

Luego (como root) instalamos las dependencias necesarias. En Debian sería:

# aptitude update
# aptitude install libreadline5-dev


Procedemos (como usuario) a compilar e instalar la extensión en cuestión:

$ ruby extconf.rb
$ make
$ make install


Y con eso ya deberíamos disfrutar nuevamente de la consola interactiva de Rails sin problemas.

Resaltado de sintaxis HAML en Gedit

lunes, febrero 28, 2011

Trabajando con Ruby On Rails me ha tocado escribir código usando HAML. Particularmente no me agrada mucho (entre otras cosas porque no tiene soporte multilínea, porque no identa correctamente las cadenas de texto plano, porque agrega otra capa más de interpretación a la aplicación, etc) pero cuando toca usarlo es bueno hacerlo con un buen soporte. Y cuando hablo de soporte me refiero al resaltado de sintaxis.

Para escribir código usualmente uso un editor de texto (Gedit o Geany), así que en ésta receta explicaré como agregar soporte para el resaltado de sintaxis en Gedit.

Primero agregamos soporte para que las extensiones usadas comúnmente en Rails sean reconocidas por el sistema. Abrimos una terminal y escribimos:

wget http://dl.dropbox.com/u/16349833/rails.xml 
sudo cp rails.xml /usr/share/mime/packages/rails.xml 
sudo update-mime-database /usr/share/mime

Luego agregamos los archivos de definición de sintaxis en la carpeta del sourceview de GTK ejecutando:

wget http://dl.dropbox.com/u/16349833/gedit_rails_syntax.zip
sudo unzip gedit_rails_syntax.zip -d /usr/share/gtksourceview-2.0/language-specs


Ahora con nuestro editor de texto favorito (y como root) abrimos el archivo /usr/share/gtksourceview-2.0/language-specs/ruby.lang para modificar el sourceview de GTK y agregar soporte para nuevas extensiones. Buscamos la línea:

*.rb

Y la cambiamos por:

*.rb;*.rake;*.rjs

Por último, abrimos el archivo /usr/share/gtksourceview-2.0/language-specs/html.lang y buscamos la línea que dice:

*..html;*.htm

Y la cambiamos por:

*.html;*.htm;*.erb;*.rhtml

Cerramos todas las instancias de Gedit y al abrir de nuevo ya nuestro código HAML debería verse resaltado.


Existen recetas que instalan una serie de plugins (con soporte para haml, rjs, etc) y te dejan al Gedit como TextMate, pero como no me gusta TextMate entonces prefiero hacerlo a patica xD

Espero que la receta les haya servido de ayuda.

Referencias:
http://groups.google.com/group/haml/browse_thread/thread/6c8babd81a46b6b8/b5100d80d9182c71?pli=1
http://blog.adsdevshop.com/2008/04/19/erb-syntax-highlighting-in-gedit/

Error con Ruby 1.8 y Rails 1.2.6 en Debian Squeeze

lunes, octubre 05, 2009

Estaba yo una tarde de lo más tranquilo, programando mi sistema de compras de café verde mientras tarareaba una canciónde Bloodbath xD. En una de esas me dispongo a correr las migraciones de mi proyecto para actualizar la base de datos y para mi sorpresa ¡la migración falla!. El error (nada explícito) a continuación:

$ rake db:migrate
(in /home/satanas/proyectos/cvacafe/sicca)
rake aborted!
{:root=>"(as the the label for a named route) will become a shortcut for map.connect '', so find another name"} is not a symbol

(See full trace by running task with --trace)


Al ver la verbosidad del mensaje invoco el comando pero con la opción --trace tal como me lo sugiere la advertencia y obtengo esto:

$ rake db:migrate --trace
(in /home/satanas/proyectos/cvacafe/sicca)
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
rake aborted!
{:root=>"(as the the label for a named route) will become a shortcut for map.connect '', so find another name"} is not a symbol
/usr/lib/ruby/1.8/deprecated.rb:176:in `instance_method'
/usr/lib/ruby/1.8/deprecated.rb:176:in `deprecate'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.6/lib/action_controller/routing.rb:994
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:342:in `new_constants_in'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.6/lib/action_controller/base.rb:4
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:342:in `new_constants_in'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.6/lib/action_controller.rb:37
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:342:in `new_constants_in'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/initializer.rb:166:in `require_frameworks'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/initializer.rb:166:in `each'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/initializer.rb:166:in `require_frameworks'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/initializer.rb:87:in `process'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/initializer.rb:47:in `send'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/initializer.rb:47:in `run'
/home/satanas/proyectos/cvacafe/sicca/config/../config/environment.rb:13
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:342:in `new_constants_in'
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.4/lib/active_support/dependencies.rb:495:in `require'
/usr/lib/ruby/gems/1.8/gems/rails-1.2.6/lib/tasks/misc.rake:3
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:617:in `call'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:617:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:612:in `each'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:612:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:578:in `invoke_with_call_chain'
/usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:571:in `invoke_with_call_chain'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:588:in `invoke_prerequisites'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:585:in `each'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:585:in `invoke_prerequisites'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:577:in `invoke_with_call_chain'
/usr/lib/ruby/1.8/monitor.rb:242:in `synchronize'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:571:in `invoke_with_call_chain'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:564:in `invoke'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2019:in `invoke_task'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `top_level'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `each'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `top_level'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2036:in `standard_exception_handling'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1991:in `top_level'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1970:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2036:in `standard_exception_handling'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1967:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.8.3/bin/rake:31
/usr/bin/rake:19:in `load'
/usr/bin/rake:19


Pues al igual que ustedes, quedé un poco chino con el error (a no ser que alguno de ustedes sea un Ruby developer :P), pero me puse a revisar unos archivos claves: /usr/lib/ruby/1.8/deprecated.rb en la línea 176 y /usr/lib/ruby/gems/1.8/gems/actionpack-1.13.6/lib/action_controller/routing.rb en la línea 994 (béndito sea el Software Libre xD) y descubrí que el problema era con la llamada a una tal función deprecate que esperaba un símbolo y no sé que diablos estaba recibiendo.

Le pregunté a un amigo (que programa conmigo el mismo sistema y no tenía el problema) por sus versiones de Ruby, Rails y las gemas. Teníamos todas las versiones exactamente iguales excepto la de Ruby; yo tenía la 1.8.7.174 y él tenía la 1.8.7.72.

Sí, aunque ustedes no lo crean yo aún uso Rails 1.2.6 con Ruby 1.8 y resulta que Debian Squeeze (testing al momento de escribir esto) me actualizó el paquete de Ruby estropeando la compatibilidad de Ruby y Rails. Sí, también sé que debo migrar a Rails 2 ¡¡¡cuanto antes!!!

Bueno la cuestión la solucioné de una manera relativamente fácil, purge mi instalación de ruby:

# aptitude purge ruby ruby1.8-dev ri ri1.8 rdoc rdoc1.8 irb irb1.8 ruby1.8-examples libreadline-ruby libopenssl-ruby libdbi-ruby libdbd-mysql-ruby libdbd-pg-ruby libdbd-odbc-ruby libdbd-sqlite3-ruby libpgsql-ruby libmysql-ruby

Cambié mis repositorios a los de Debian Lenny (estable para la fecha) (/etc/apt/sources.list):

deb http://ftp.us.debian.org/debian lenny main contrib non-free
deb-src http://ftp.us.debian.org/debian lenny main contrib non-free


Actualicé la lista de paquetes:

# aptitude update

Instalé nuevamente Ruby (pero la versión de Lenny):

# aptitude install ruby ruby1.8-dev ri ri1.8 rdoc rdoc1.8 irb irb1.8 ruby1.8-examples libreadline-ruby libopenssl-ruby libdbi-ruby libdbd-mysql-ruby libdbd-pg-ruby libdbd-odbc-ruby libdbd-sqlite3-ruby libpgsql-ruby libmysql-ruby

Apliqué retención a todos los paquetes anteriores (para que en una futura actualización no pase lo mismo):

# aptitude hold ruby ruby1.8-dev ri ri1.8 rdoc rdoc1.8 irb irb1.8 ruby1.8-examples libreadline-ruby libopenssl-ruby libdbi-ruby libdbd-mysql-ruby libdbd-pg-ruby libdbd-odbc-ruby libdbd-sqlite3-ruby libpgsql-ruby libmysql-ruby

Y volví a poner mis repos de Squeeze:

deb http://ftp.us.debian.org/debian testing main contrib non-free
deb-src http://ftp.us.debian.org/debian testing main contrib non-free


Ahora tengo mi obsoleto y anticuado Ruby 1.8.7.72 pero que me funciona de maravillas con Rails 1.2.6 xD

Cambio y fuera

Ruby on Rails Inflector en español

lunes, junio 22, 2009

El módulo Inflectors de Ruby on Rails transforma palabras de singular a plural, nombres de clases a nombres de tablas, nombres de clases a claves foráneas, entre otros. Sin embargo éste módulo no soporta pluralización en español.

Si quieremos reemplazar la pluralización que trae por defecto Rails (inglés) y crear la nuestra en español solo debemos agregar estas reglas al final del archivo config/environment.rb:

# Limpiamos todas las inflecciones existentes
Inflector.inflections.clear

# Agregamos las reglas de inflección
Inflector.inflections do |inflect|
inflect.plural /([taeiou])([A-Z]|_|\$)/, '\1s\2'
inflect.plural /([rlnd])([A-Z]|_|$)/, '\1es\2'
inflect.singular /([taeiou])s([A-Z]|_|$)/, '\1\2'
inflect.singular /([rlnd])es([A-Z]|_|$)/, '\1\2'
end

La primera regla dice algo como: "Todas las palabras que terminen en t, a, e, i, o, u y que luego tengan una letra mayúscula, un underscore o un fin de línea entonces se pluralizan con S", mientras que la segunda regla dice: "Todas las palabras que terminen en r, l, n, d y que luego tengan una letra mayúscula, un underscore o un fin de línea entonces se pluralizan con ES". Las reglas tres y cuatro se interpretan siguiendo el mismo criterio pero de forma inversa. Así, "casa" se pluraliza como "casas" y "canción" se pluraliza como "canciones".

Dejaré como tarea para el lector estudiar de manera detallada las expresiones regulares usadas en las reglas, pero les dejaré una pista:
Es necesario recordar que en una expresión regular los paréntesis son signos de agrupación y cada expresión entre paréntesis corresponde a un grupo. Se puede hacer referencia a la expresión asociada a un grupo mediante una barra invertida "\" y el número del grupo. Es por eso que en la expresión regular del Inflector se usa el \1 y el \2

Con el código anterior ya tenemos configurada nuestra pluralización en español. Podemos probarla agregando el código a un proyecto existente y abriendo una consola de Rails:
$ cd proyecto_existente_de_rails
$ script/console
Loading development environment.
>>'prueba'.pluralize
=> "pruebas"

Observamos que ahora el string 'prueba' está en plural. Sin embargo existe un bug en la versión 1.2.6 de Rails (quizás esté corregido en las versiones posteriores pero aún no lo he confirmado) y es que si intentamos pluralizar un string que contenga expresiones que cumplan ambos patrones del inflector entonces obtendremos una sola palabra pluralizada, por ejemplo:
>>'prueba_cancion'.pluralize
=> "prueba_canciones"

Se debe extender la clase Inflector y modificar los métodos pluralize y singularize. El código lo podemos insertar en el mismo archivo config/environment.rb y sería algo como:

# Extender la clase Inflector
module Inflector
def pluralize(word)
result = word.to_s.dup

if word.empty? || inflections.uncountables.include?(result.downcase)
result
else
inflections.plurals.each { |(rule, replacement)| result.gsub!(rule, replacement) }
result
end
end

def singularize(word)
result = word.to_s.dup
if inflections.uncountables.include?(result.downcase)
result
else
inflections.singulars.each { |(rule, replacement)| result.gsub!(rule, replacement) }
result
end
end
end

Si revisamos el código fuente de los métodos pluralize y singularize veremos que la diferencia está en la instrucción break if en las líneas 112 y 132 respectivamente:
112:   inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
...
132: inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }

Solo debemos eliminar ese par de instrucciones para que entonces la regla sea aplicable a más de un patrón al mismo tiempo.

Por los momentos es todo. Espero sea de utilidad este pequeño pero interesante tip

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.

La Aventura de Ruby on Rails (Parte 2): El entorno de desarrollo

miércoles, enero 14, 2009

En la entrega pasada instalamos Ruby y Rails con todos los complementos necesarios para crear una aplicación web. Ahora vamos a configurar nuestro entorno de desarrollo para empezar a echar las primeras líneas de código.

Para aquellos que adoran las funcionalidades de un IDE como eclipse entonces les dejo este link. Desde allí pueden descargar EasyEclipse; un entorno basado en Eclipse pero viene listo para programar en Ruby on Rails (trae muchas otras funcionalidades pero no me he tomado la molestia de revisarlo al detalle).

A mi, sin embargo, me gusta más la simplicidad y siempre he pensado que los IDE consumen muchos recursos, es por eso que un simple editor de textos es la solución perfecta a mis necesidades. A partir de este punto explicaré como transformar al Gedit (el editor por defecto de GNOME) en una poderosa herramienta de desarrollo.

La siguiente receta está basada en un trabajo del amigo Joselo en su blog NationCode: Gedit como Textmate mejorado para GNU/Linux pero adaptada para cubrir mis necesidades. Todos los archivos necesarios para aplicarla puedes descargarlos de aquí

Dentro del archivo comprimido está un script que realiza la instalación por sí solo, lo único que debes hacer es descomprimirlo, entrar a la carpeta y ejecutarlo con permisos de súper usuario; algo más o menos así:
tar -xzf gedit-dev-1.2.tar.gz
cd gedit-dev
sudo sh gedit-dev-sh


Si quieres instalarlo uno a uno tú mismo entones continúa leyendo la receta :D

A partir de este punto ejecutaremos las instrucciones como súper usuario. Lo primero que haremos será instalar los plugins extra de Gedit
# aptitude install gedit-plugins

Posteriormente editamos el archivo /etc/mime.types y agregamos estas líneas al final:
text/x-ruby-source                           rhtml html.erb
text/x-eruby rjs
text/x-yaml yml


A continuación actualizamos las extensiones mime types:
update-mime-database /usr/share/mime

Nos posicionamos en la carpeta descomprimida de gedit-dev y copiamos el archivo x-rhtml.xml a la carpeta /usr/share/mime/packages:
cp mime/x-rhtml.xml /usr/share/mime/packages

Copiamos las definiciones de rhtml, ruby, rjs y yml a la carpeta /usr/share/gtksourceview-2.0/language-specs:
cp langs/*.lang /usr/share/gtksourceview-2.0/language-specs

Ahora salimos del modo súper usuario (pero nos quedamos dentro de la carpeta gedit-dev) y nos devolvemos a nuestro usuario regular. Instalamos los otros plugins de Gedit:
mkdir -p ~/.gnome2/gedit/plugins/
cp -R plugins/* ~/.gnome2/gedit/plugins/


Instalamos los recortes para el Gedit
mkdir -p ~/.gnome2/gedit/snippets/
cp -R snippets/* ~/.gnome2/gedit/snippets/


Y luego instalamos los estilos o temas de colores para el resaltado de la sintaxis:
mkdir -p ~/.gnome2/gedit/styles/
cp styles/* ~/.gnome2/gedit/styles/


Ahora configuramos el Gedit. En el menú Editar->Preferencias, pestaña Ver debemos desactivar el ajuste de texto, mostramos los números de línea, la línea actual y el margen derecho; establecemos el margen en la columna 80 y resaltamos la pareja del corchete.



En la pestaña Editor establecemos el ancho del tabulador a 2, insertamos espacios en lugar de tabuladores, activamos la sangría automática, desactivamos la copia de respaldo y autoguardamos cada 10min.



En la pestaña Tipografía seleccionamos el tema Serious y en Complementos activamos:
  • Dibujar espacios

  • Panel del examinador de archivos

  • Recortes

  • Salvasesiones

  • Snap Open


El resultado un simple pero poderoso editor listo para Ruby on Rails :)

La Aventura de Ruby on Rails (Parte 1): El inicio

viernes, diciembre 26, 2008

Este post es el inicio de una serie en la que pretendo ilustrar mis experiencias e impresiones en el mundo de Ruby on Rails. Debo decir que al momento de escribir esto conozco realmente poco (por no decir nada) sobre Ruby, Rails y afines, así que empezaré desde cero. Vamos con un poco de teoría

  • ¿Qué es Ruby?
    Ruby es un lenguaje de programación interpretado, reflexivo y orientado a objetos, creado por el programador japonés Yukihiro Matsumoto y distribuido bajo licencias libres. Combina una sintaxis inspirada en Python y Perl, con características de programación orientada a objetos similares a Smalltalk. Comparte también funcionalidad con otros lenguajes de programación como Lisp, Lua, Dylan y CLU

  • ¿Qué es Ruby on Rails?
    Ruby on Rails (RoR o Rails) es un entorno de desarrollo web de código abierto escrito en Ruby y optimizado para satisfacción de los programadores y de la productividad. Te permite escribir aplicaciones web siguiendo el paradigma de la arquitectura Modelo Vista Controlador (MVC) y su filosofía principal es: Favorecer la convención antes que la configuración

  • ¿Qué son las Gemas de Ruby o Ruby Gems?
    Las Gemas son paquetes autocontenidos utilizados por Ruby oficialmente para distribuir librerías y aplicaciones. Son empleadas por Rails para la instalación de su entorno

  • ¿En qué consiste la arquitectura MVC?
    En pocas palabras podemos decir que la arquitectura MVC separa una aplicación en 3 capas: el Modelo, la Vista y el Controlador. El Modelo trabaja directamente con las fuentes de datos (bases de datos, sockets, etc) y es el encargado de la integridad de la información. La Vista es la interfaz que usará la aplicación para interactuar con el usuario y la que se usará para mostrar los datos del modelo. La Vista debe ser "tonta" en el sentido de que no debe tener conocimiento alguno sobre las fuentes de datos, los eventos u otros, solo debe mostrar la información que se le indique. Por último, el controlador es quien maneja los eventos de la aplicación, digamos que es la "pega" entre el Modelo y la Vista; puede interactuar con las funciones del modelo y envía información a la Vista.

Dicho esto empecemos con la instalación del ambiente Ruby on Rails. Las siguientes instrucciones están hechas para Debian Lenny 5.0 e instalarán Ruby 1.8 y Rails 1.2.6.

Instalamos Ruby y todos los paquetes necesarios (como super usuario):
# aptitude update
# aptitude install build-essential ruby ruby1.8-dev ri ri1.8 rdoc rdoc1.8 irb irb1.8 ruby1.8-examples libreadline-ruby libopenssl-ruby libdbi-ruby libdbd-mysql-ruby libdbd-pg-ruby libdbd-odbc-ruby libdbd-sqlite3-ruby libpgsql-ruby libmysql-ruby mysql-server mysql-client


Descargamos los paquetes necesarios para Ruby si no los tenemos (ver la página de RubyForge para más información):
$ wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz
$ wget http://rubyforge.org/frs/download.php/26547/activesupport-1.4.4.gem
$ wget http://rubyforge.org/frs/download.php/28328/actionpack-1.13.6.gem
$ wget http://rubyforge.org/frs/download.php/28331/actionmailer-1.3.6.gem
$ wget http://rubyforge.org/frs/download.php/28325/activerecord-1.15.6.gem
$ wget http://rubyforge.org/frs/download.php/28334/actionwebservice-1.2.6.gem
$ wget http://rubyforge.org/frs/download.php/19878/rake-0.7.3.gem
$ wget http://rubyforge.org/frs/download.php/28337/rails-1.2.6.gem


Instalamos el manejador de paquetes de Ruby (RubyGems):
# tar -xvzf rubygems-1.2.0.tgz
# cd rubygems-1.2.0
# ruby setup.rb
# ln -s /usr/bin/gem1.8 /usr/bin/gem


Y por último instalamos las gemas que acabamos de descargar:
# gem install activesupport-1.4.4.gem
# gem install actionpack-1.13.6.gem
# gem install actionmailer-1.3.6.gem
# gem install activerecord-1.15.6.gem
# gem install actionwebservice-1.2.6.gem
# gem install rake-0.7.3.gem
# gem install rails-1.2.6.gem


Es importante destacar que se deben instalar las versiones tal cual como aparecen aquí y en el mismo orden pues son las que funcionan correctamente entre sí.

Para comprobar que todo ha ido bien basta con hacer:
$ ruby --version
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
$ rails --version
Rails 1.2.6


Con esto ya podemos empezar a crear aplicaciones en Rails :D pero dejaremos esa parte para la próxima entrega.

Acá dejaré un script que se puede utilizar para instalar Ruby on Rails al toque, solo basta ejecutarlo como super usuario y él se encargará de hacer el resto ;)
#!/bin/bash
#===================================================
#
# ruby_instalacion.sh - Script en bash que permite instalar Ruby On Rails
# al vuelo
#
# Copyright (C) 2008: Wil Alvarez
#
#===================================================

# Instalar Ruby
aptitude update
aptitude install -y build-essential ruby ruby1.8-dev ri ri1.8 rdoc rdoc1.8 irb irb1.8 ruby1.8-examples libreadline-ruby libopenssl-ruby libdbi-ruby libdbd-mysql-ruby libdbd-pg-ruby libdbd-odbc-ruby libdbd-sqlite3-ruby libpgsql-ruby libmysql-ruby

# Instalar RubyGems
wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz
tar -xvzf rubygems-1.2.0.tgz
cd rubygems-1.2.0
ruby setup.rb
GEM=/usr/bin/gem
if [ -n $GEM ]; then
rm -f /usr/bin/gem
fi
ln -s /usr/bin/gem1.8 /usr/bin/gem
cd ..
rm -rf rubygems-1.2.0/

# Instalar Rails
wget http://rubyforge.org/frs/download.php/26547/activesupport-1.4.4.gem
wget http://rubyforge.org/frs/download.php/28328/actionpack-1.13.6.gem
wget http://rubyforge.org/frs/download.php/28331/actionmailer-1.3.6.gem
wget http://rubyforge.org/frs/download.php/28325/activerecord-1.15.6.gem
wget http://rubyforge.org/frs/download.php/28334/actionwebservice-1.2.6.gem
wget http://rubyforge.org/frs/download.php/19878/rake-0.7.3.gem
wget http://rubyforge.org/frs/download.php/28337/rails-1.2.6.gem

gem install activesupport-1.4.4.gem
gem install actionpack-1.13.6.gem
gem install actionmailer-1.3.6.gem
gem install activerecord-1.15.6.gem
gem install actionwebservice-1.2.6.gem
gem install rake-0.7.3.gem
gem install rails-1.2.6.gem

rm activesupport-1.4.4.gem actionpack-1.13.6.gem actionmailer-1.3.6.gem activerecord-1.15.6.gem actionwebservice-1.2.6.gem rake-0.7.3.gem rails-1.2.6.gem