Modulos

Tuesday, 11 December , 2007

Bueno en este post voy a mostrar un ejemplo sencillo con módulos de ruby, muy básicamente un módulo es una colección de métodos y constanstes, los métodos en un módulo pueden ser métodos de instancia o métodos de módulo. Los métodos de instancia aparecen como métodos en una clase cuando el módulo es incluido, los métodos de módulo no. Al contrario los métodos de módulo pueden ser llamados sin crear un objeto encapsulado, mientras que los métodos de instanacia no. (ref: http://www.ruby-doc.org/core/classes/Module.html)

Veamos un ejemplo dónde tenemos algunos métodos de instancia:

module Saludo
  attr_accessor :saludo

  def agregar_nombre
    @saludo << " Pepe"
  end
end

class SaludoNuevo
  include Saludo

  def saludo= value
    @saludo = value
  end
end

s =  SaludoNuevo.new
s.saludo = 'Hola'
puts s.saludo
s.agregar_nombre
puts s.saludo

La salida de este programa es la siguiente:

=> Hola
=> Hola Pepe

Cómo podemos ver los métodos declarados dentro del Módulo Saludo aparecen cómo métodos de instancia de la clase SaludoNuevo, dado que Saludable “Mixed in” en SaludadorNuevo. Los Mixins son la manera en que ruby resuelve la Herencia Múltiple (Ya veremos algunos ejemplos más adelante).

Ahora agregamos un método de Módulo:

module Saludo
  attr_accessor :saludo

  def agregar_nombre
    @saludo << " Pepe"
  end

  def Saludo::general
    "Hola a todos"
  end
end

class SaludoNuevo
  include Saludo

  def saludo= value
    @saludo = value
  end
end

puts Saludo::general

s =  SaludoNuevo.new
s.saludo = 'Hola'
puts s.saludo
s.agregar_nombre
puts s.saludo

Y la salida es:

=> Hola a todos
=> Hola
=> Hola Pepe

Ahora vamos a agregar una variable de instancia en el módulo Y la vamos a usar y modificar desde la clase cliente:

module Saludo
  attr_accessor :saludo, :nombres

  def initialize
    @nombres = ["Pepe", "Gaston", "David"]
  end

  def agregar_nombre
    @saludo << " Pepe"
  end

  def Saludo::general
    "Hola a todos"
  end

end

class SaludoNuevo
  include Saludo

  def saludo= value
    @saludo = value
  end

  def saludo_general_con_nombres
    "Hola " + @nombres.join(', ')
  end

end

s = SaludoNuevo.new
puts s.saludo_general_con_nombres

# Modifico la variable de instancia @nombres Heredada del módulo "Saludo"
s.nombres << "Dave"
puts s.saludo_general_con_nombres

# Creo un nuevo objeto de Saludo Nuevo y modifico @nombres para
# ver que es una variable de instancia
s2 = SaludoNuevo.new
s2.nombres = ["Matz", "Kent", "Bruce"]
puts s2.saludo_general_con_nombres

puts s.saludo_general_con_nombres

la salida es:

=> Hola Pepe, Gaston, David
=> Hola Pepe, Gaston, David, Dave
=> Hola Matz, Kent, Bruce
=> Hola Pepe, Gaston, David, Dave

Bueno esto fue todo por ahora, cortito y sencilllo.

Monit y Mongrel

Monday, 19 November , 2007

Hace un tiempo escuché hablar de monit una herramienta que sirve para monitorear los mongrels (eso había escuchado yo…) pero en realidad es mucho más que eso! con monit podemos:

  • Monitorear servicios y reiniciarlos o matarlos si están consumiendo mucha memoria o procesador.
  • Iniciar un servicio que no está corriendo (y debería estarlo)
  • Monitorear archivos, directorios, dispositivos
  • Y mucho más…

Esta herramienta me viene al pelo dado que he estado experimentando algunos problemas con el mongrel (se cae o comienza a consumir mucha memoria). Para instalarlo en debian:

apt-get install monit

el archivo de configuracion está en /etc/monit/monitrc googleando un poco encontré este sitio
http://monitr.atmos.org/ el cual genera la configuracion para monit a partir de
los archivos de configuracion de mongrel_cluster.
Una vez que ya tenemos listo nuestro archivo de configuración tenemos que “activar” el monit y lo hacemos editando
el archivo /etc/default/monit cambiamos startup=0 por startup=1
Una de las cosas buenas de monit es que trae un sistema de monitoreo por web que por defecto está en el puerto 2812 (esto se especifica en el archivo de configuración) entonces lo podemos ver en http://localhost:2812/
Actualemente estoy monitoreando 4 mongrels y el nginx y funciona bárbaro, para los mongrels cuando detecta que consumen más de 100mb RAM los reinicia y cuando detecta que no responden (via http) también .
Acá les dejo un screenshot:

monit web

RubyGems bastante lento

Thursday, 15 November , 2007

Tengo un server con un micro AMD-K6(tm) 3D processor y 128 MB de RAM con un Debian GNU/Linux con ruby 1.8 RubyGems 0.9.4 mogrel y nginx 0.4.13-2, intentando hacer un gem update noté que se tomaba su tiempo, Updating installed gems…, luego de unas cuantas horas seguía en el mismo lugar, al parecer el problema está cuando cuando arma las lista de dependencias de las gemas, googleando un poco encontré esto: http://blog.segment7.net/articles/2007/10/13/rubygems-beta-0-9-4-5 una versión beta de rubygems que soluciona este problema, entonces pasé a instalarla:

gem update --system --source http://segment7.net/

Ahora funciona bastante mejor!!! al menos demora minutos y no horas como antes, como dice en el sitio este release mejora el manejo de memoria.

Grupo de usuarios de Ruby del litoral

Sunday, 02 September , 2007

Esta semana hablando con algunos chicos de lug oro verde nos surgió la idea de hacer una reunión con todos aquellos que estamos interesados en ruby y ruby on rails, entonces pensé… por que no crear un grupo de usuarios de ruby del litoral? y acá está el resultado: tenemos wiki y lista de correo , desde ya litoraleños están todos invitados a participar, los esperamos!!!.

http://www.rubylit.com.ar/

Bueno, lo primero que quiero hacer es agradecer a la gente de lugoroverde por invitarnos a las jornadas, la charla estuvo muy buena (mejor que de lo que yo creía ) la gente quedó muy entusiasmada con esto de Rails, luego de algo de teoría hicimos un pequeño ejemplo práctico, creamos un modelo y mostramos el scaffold y como personalizar las vistas creadas.

Les dejo acá los slides de la charla dwsr.pdf
La última parte de la charla

El sábado 25 de agosto voy a dar una charla con Esteban Fornal (más conocido como Chaco) en las 4tas jornadas regionales de software libre de oro verde en Entre Ríos, la charla va a ser una introducción a Ruby on Rails, mostraremos las principales características del framework (al menos las que más nos gustan a nosotros) y si hay tiempo vamos a hacer algo de práctica. Nuestro prinicipal objetivo es motivarlos a que prueben RoR por cuenta propia, y entren en este marivolloso mundo de la programación ágil y divertida.

Los esperamos!!!

Emacs22 + emacs-rails

Friday, 17 August , 2007

Acabo de actualizar a emacs22, junto con la última versión de emacs-rails. Emacs22 viene con varias novedades, entre ellas soporte completo para unicode, acá hay un muy buen artículo con las nuevas carácterísticas.

Para los debianistas:
 apt-get install emacs22

luego nos vajamos el emacs-rails

  wget -c http://files.rubyforge.mmmultiworks.com/emacs-rails/emacs-rails-0.5.99.5.tar.gz

o lo bajamos a mano desde acá http://rubyforge.org/frs/?group_id=1484&release_id=11880

Luego lo colocamos en el folder ~/.emacs.d/site-lisp/emacs-rails/ y listo (ante cualquier duda leer http://dima-exe.ru/rails-on-emacs , yo no tuve problemas por que ya tenía la vieja versión instalada).

Hace casi un año que estoy usando emacs y no deja de sorprenderme, me encanta eso que “podés hacer todo con las telcas”, además también se puede utilizar sin un entorno gráfico (y va a ser exactamente igual sólo que en modo texto), Pruébenlo!. Para finalizar les dejo un screenshot para que vean como quedó, la verdad muy bueno.

emacs22-screenshot

Rake tasks para log/ tmp/ y cache/

Wednesday, 18 July , 2007

Acá les dejo algunas tareas de rake que suelo agregar cuando comienzo un proyecto nuevo, son para
sacar las cosas que no tienen que estar bajo control de versión y para crear los archivos de log (cuando lo necesitemos):

lib/tasks/log.rake


namespace :log do

  desc "Crear los directorios y archivos de log"
  task :create do

    system 'mkdir -p log'
    system '> log/development.log'
    system '> log/production.log'
    system '> log/server.log'
    system '> log/test.log'

  end

  desc "Cambia el grupo del directorio los archivos de log a www-data y pone
  permisos de lectura/escritura para el grupo"
  task :set_permissions_for_apache do

    system 'chgrp -R www-data log'
    system 'chmod -R g+rw log/'

  end

  desc "Saca los archivos de log del svn"
  task :remove_svn do

    system 'svn remove log/*'
    system "svn commit -m 'Estas cosas no van en el svn'"
    system "svn propset svn:ignore '*.log' 'log/'"
    system 'svn update log/'
    system "svn commit -m 'Ingnorar los archivos en log/'"
  end

end

lib/tasks/tmp.rake


namespace :tmp do

  desc "Cambia el grupo del directorio los archivos de log a www-data y pone
        permisos de lectura/escritura para el grupo"
  task :set_permissions_for_apache do

    system 'chgrp -R www-data tmp'
    system 'chmod -R g+rw tmp'

  end

  desc "Saca los archivos de tmp del svn"
  task :remove_svn do

    system 'svn remove tmp/cache/*'
    system 'svn remove tmp/sessions/*'
    system 'svn remove tmp/sockets/*'

    system "svn commit -m 'Los archivos temporales no van en el svn'"

    system 'svn propset svn:ignore "*" tmp/'
    system 'svn propset svn:ignore "*" tmp/cache/'
    system 'svn propset svn:ignore "*" tmp/sessions/'
    system 'svn propset svn:ignore "*" tmp/sockets/'

    system 'svn update tmp/'
    system "svn commit -m 'Ingnorar los archivos en tmp/'"
  end
end

lib/tasks/db.rake


namespace :db do

  desc "Saca el archivo database.yml del svn"
  task :rm_conf_file_svn do
    system 'svn move  config/database.yml config/database-ejemplo.yml'
    system "svn commit -m 'El archivo database.yml no va en el svn'"
    system "svn propset svn:ignore 'database.yml' 'config/'"
    system 'svn update config/'
    system "svn commit -m 'Ingnorar el archivo config/database.yml'"
    system 'cp  config/database-ejemplo.yml  config/database.yml'
  end

  desc "Genera el archivo database.yml"
  task :gen_conf_file do
    system 'cp  config/database-ejemplo.yml config/database.yml'
  end
end

He publicado una biblioteca que genera imágenes para representar piezas dentarias en odontogramas, entre otras cosas las biblioteca permite crear .png .jpg, etc de piezas dentarias en blanco o con sus caras pintadas de un color (similar a la ficha de odontograma en papel). El proyecto en rubyforge es http://rubyforge.org/projects/imagetooth/, También está disponible como gema de ruby:

gem install imagetooth

La biblioteca tiene un script ejecutable que permite crear las imágenes de la sigueinte manera:

 ruby imagetooth.rb  --image wwwww.png --folder ./

Esto genera una imágen de un diente en blanco en el directorio actual dónde el wwwww.png representa lo siguiente:

[arriba][derecha][abajo][izquiera][centro].png

el orden de los caracateres representa la cara del diente a pintar y el caracter el color

  • w - White
  • g - Green
  • b - Blue
  • n - Black
  • r - Red

algunos ejemplos:

generar un diente con la de arriba pintada de rojo

 ruby imagetooth.rb  --image rwwww.png --folder ./

generar un diente con la cara de arriba pintada de rojo y la cara del centro de verde:

 ruby imagetooth.rb  --image rwwwg.png --folder ./

generar un diente con la cara de arriba pintada de rojo, la cara del centro de verde y la de la izquiera de negro:

 ruby imagetooth.rb  --image rwwng.png --folder ./

además brinda la posibilidad de generar todas las combinaciones posibles(muy útil para tener las imágenes pregeneradas para un desarrollo web por ej.):

 ruby imagetooth.rb --all  --folder images/

Esto da como resultado 3125 imágenes (con 5 colores y 5 caras de dientes) divididas en directorios de acuerdo al

primer caracter del nombre de la imágen:

images/w/
images/b/
images/g/
images/n/
images/r/

La siguiente imagen fue generada utilizando imagetooth:
Odontograma de ejemplo
Para que el que tenga que desarrollar una aplicación que gestione odontogramas esta biblioteca le puede servir de base, y probablemente no tenga que partir desde cero como fue mi caso.

 http://imagetooth.rubyforge.org/

Actualmente estoy trabajando en un módulo de una aplicación web cuyo objetivo es presentar reportes de accesos a un predio, la aplicación está desarrollada en php y postgresql, los reportes están basados en vistas, dónde tengo una “vista base” llamada “stats_ingresos”, y las demás vistas hacen uso de “stats_ingresos”. Todo muy lindo, pero actualmente este sistema es muy lento, las consultas a estas vistas demoran más 2 minutos lo cual es inaceptable para una aplicación web, entonces decidí pasar esta vista base a tabla, con lo cual el costo de la consulta se reduce a 0. Obviamente esta solución tiene una desvetaja, tengo que actualizar la tabla “stats_ingresos” perdiódicamente, la actualización se va a realizar una vez por día y se actualizarán todos los accesos del mes (ya sé que esto se puede mejorar).
Para ir al grano, he decidido implentar este script de update con ruby + active_record y como metodología bdd usando rspec.
Esta es la tabla que va a reemplazar a la “vista base”:

CREATE TABLE stats_ingresos (
  id SERIAL NOT NULL,
  nombre VARCHAR(25),
  apellido VARCHAR(25),
  dni VARCHAR(12),
  id_institucion INTEGER,
  institucion VARCHAR(50),
  dia SMALLINT,
  mes SMALLINT,
  anio SMALLINT,
  ts timestamp,
  PRIMARY KEY  (id)
);

Read the rest of this entry »