Tag Archives: Ruby

How to know, in ruby, which methods have been added and by whom?

If you are not very careful, monkeypatching could be very harmful. One thing to remember is that you should never override a method to add funcionality, for those kind of thinks you must use alias chain method pattern, a safer way of doing that.

For the rest of the monkeypatching, i.e. add new methods, you could debug them really easy with something like this:

class Class
   def method_added(method_name)
      puts "#{method_name} added to #{self}, callstack:"
      puts caller.map{|line| "\t#{line}" }.join("\n")
   end
end

You can always add more code to filter by class or by method’s name. Let’s see an example:

$ more example.rb 
require 'date'
require 'time'
 
class Class
   def method_added(method_name)
      return if %w(method_added).include? method_name.to_s
      puts "#{method_name} added to #{self}, callstack:"
      puts caller.map{|line| "\t#{line}" }.join("\n")
   end
end
 
class Time
   def to_date
      Date.ordinal self.year, self.yday
   end
end
 
class Date
   def to_time
      Time.parse self.to_s
   end
end
 
raise "to_date not working" unless
   Time.now.to_date == Date.today
raise "to time not working" unless
   Time.now.to_date.to_time == Date.today.to_time

The output will be:

$ ruby example.rb 
to_date added to Time, callstack:
	example.rb:13
to_time added to Date, callstack:
	example.rb:19

Nice, isn’t it?. Remember to be carefull with your monkeypatching, with great power comes great responsibility, it’s just a tool, neither magic nor the panacea.

Visualización de la documentación de todas las gemas instaladas

La documentación de las gemas de ruby se genera a partir del código fuente mediante rdoc. Después de eso puedes optar por ver individualmente cada una o usar gem server.

Para poder mejorar todo esto podemos usar par de útiles herramientas: (1) la plantilla para rdoc, hanna; y (2)bdoc como alternativa a gem server para visualizar la documentación.

Hanna es una plantilla para rdoc que mejora notablemente el formato por defecto. Podemos ver la diferencia fácilmente, por ejemplo, en la documentación de rspec con el formato típico vs la documentación hecha con hanna. La instalación es simple:

$ sudo gem sources -a http://gems.github.com
$ sudo gem install mislav-hanna

Para que a partir de ahora se generar la documentación con esta plantilla, puede añadir a tu .gemrc la siguiente línea:

rdoc: --inline-source --line-numbers --template=hanna

Y para convertir la documentación de todas tus gemas instaladas, puedes hacer algo como esto:

$ sudo gem list | awk '{print $1}' | xargs sudo hanna --gems

Por otro lado, gracias a bdoc podremos navegar fácilmente entre todas las documentaciones.

$ sudo gem install manalang-bdoc
$ bdoc

bdoc
Ejecutando bdoc se nos abrirá en nuestro navegador por defecto listo para poder leer la documentación y poder movernos fácilmente entre las diferentes gemas (y versiones). Muy útil.

Bot personal jabber para twitter, RTwittBot

Desde hace ya un tiempo llevo usando twitter, y no, no tiene ninguna utilidad, pero me gusta hablar solo (¡está loco!). Twitter se cae cada dos por tres, pero era algo que se puede soportar (así siempre tienes algo que decir… y de lo que quejarte que a todos nos gusta quejarnos, ¡quejicas!), pero desde Mayo desactivaron el servicio que tenían de mensajería instantánea (¡como el colacao!) por jabber.

Mediante ese servicio de IM jabber teníamos el bot de twitter al cual podíamos:

  • Mandar mensajes para postear en nuestro twitter
  • Recibir mensajes de nuestro timeline de la gente que seguíamos y teníamos marcada como follow

Es decir, ahorrarnos el tener que entrar a la puta página y tener que estar dándole a f5 todo el rato. Para mi esto es un requisito para usar twitter. Si no es por IM, no lo usaría.

Estuve un tiempo en jaiku (más que nada porque era el único servicio similar que tenía el IM activado, plurk, que es molón, molón; también lo desactivó) pero ahora se ha vuelto tonto y empieza a funcionar mal. Así que pensé un poquito y dije, ¡leches, pero si te puedes montar un bot jabber en 4 pipas!, dicho y hecho, volví a twitter creándome un bot jabber, en ruby, que hace justo la misma funcionalidad que el de twitter “oficial” (aunque es solo para una persona obviamente, :P).

Lo he llamado RTwittBot (feo de cojones, lo sé), el código está en github, para hacerlo funcionar solo necesitas tener ruby y algunas gemas que he indicado en el README en github. Naturalmente, necesitarás una cuenta jabber para que sea usada por el bot (por ejemplo cualquier cuenta que tengas de gmail sirve) aparte de la tuya propia que ya usas, todo esto se encuentra explicado en github.

Por ahora lo llevo usando unos días y es bastante estable, e incluso si ocurre algún fallo en el propio bot (twitter caído, bug en el código, etc…) el bot no debería caerse sino que cambia su disponibilidad a away e indica en su estado el porqué, para volver a cambiarlo cuando todo vuelve a la normalidad :).

Cualquier duda sobre su uso o lo que sea, deja un comentario ;).

Autocompletado e historial de métodos en la consola de ruby (irb)

Hoy le toca el turno a ruby. La consola de ruby, irb, tiene bastantes opciones de configuración, permitiendo, entre otras cosas, el autocompletado de métodos e incluso guardar un historial de comandos entre sesiones.

Muy simple, simplemente añade esto a tu fichero ~/.irbrc (si no existe, lo creas):

require 'irb/completion'
 
IRB.conf[:SAVE_HISTORY] = 1000
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"
IRB.conf[:AUTO_INDENT]  = true
IRB.conf[:PROMPT_MODE]  = :SIMPLE

Puedes añadir otras opciones, e incluso personalizar el prompt el cual lo tengo a ‘simple‘ porque los otros modos son demasiado informativos para mi gusto (nunca he entendido esa manía de querer incorporar siempre el número de comando en todas las consolas de los lenguajes).

Generando javascript con código ruby embebido en rails 2.x

Hay veces que es bastante útil y cómodo devolver en una petición código javascript para que sea ejecutado en el cliente (y actualice el interfaz del usuario o lo que tenga que hacer). En vez de realizar (1) Petición, (2) Generar datos, (3) recepción y procesamiento, (4) actualizar página; pasamos a (1) Petición, (2) generar código, (3) actualizar página. Es decir nos ahorramos el parseo, además nos ahorramos tener que cargar javascript (que procesa las respuestas) en el cliente y usando jquery/mootools/* se realiza todo el proceso de forma transparente (indicando en la petición ajax que esperamos recibir un script). Esta técnica será válida solo para pequeñas actualizaciones (que son mayoría) y principalmente para temas de interfaz (que suelen ser triviales), pues en definitiva el código que no se ve, es código difícil de mantener.

En Rails tenemos templates RJS que básicamente consiste en lo que acabo de comentar pero generando javascript con wrappers en vez de usar js sin más, algo que me parece absurdo, pero eso es otro tema. Para rails 1.2.x teníamos este maravilloso plugin de Dan Webb que te permite escribir javascript con ruby embebido en él, algo como:

<% @ids_to_modified.each do |id| %>
   $('#' + <%= id %>).removeClass('<%= @class_to_remove %>').highlightFade();
<% end %>

Desde Rails 2.x ya no es necesario el uso del plugin (en parte porque ya no va), pues podemos hacer esto mismo gracias al nuevo formato de las vistas.

Ahora todas las vistas tienen el formato nombre.formato.template_engine, por ejemplo lo típico sería algo como: nombre.html.erb. Pero, ¿por qué no tener plantillas como nombre.js.erb?. De esta forma tendremos, sin incorporar plugins ni nada, la funcionalidad antes comentada, generar javascript permitiendo ruby embebido (es decir, usando erb).

Para hacernos la vida algo más simple, vendría bien incorporar ciertas funciones y helpers. En tu application.rb, no estaría de más tener algo como:

def respond_with_js
    respond_to{|format| format.js }
end

Por lo que nuestras acciones que vayan a ser llamadas mediante xhr tendrán una pinta tal que:

def vote
   # hacer lo que sea...
   respond_with_js
end

Tenemos que tener en cuenta también, que el javascript generado debe de ser válido (por ejemplo escapar comillas en las cadenas, o similares). Para asegurarnos que algo es javascript válido, nada mejor que usar json por lo que podemos pillar prestado del plugin de MinusMOR su helper (y añadirlo a application_helper.rb)

def js(data)
  if data.respond_to? :to_json
    data.to_json
  else
    data.inspect.to_json
  end
end

Por lo que ahora podemos escribir cosas tal que:

$('div.cancel').append(
    <%=js link_to('Cancelar', :action => 'cancel') %>
);
# o
alert(<%=js error_message_for(@error) %>);

Finalmente, si queremos usar partial’s tendremos que añadir este helper para soportar el nuevo formato de las plantillas (gracias a mad.ly):

def partial(name, options={})
  old_format = self.template_format
  self.template_format = :html
  js render({ :partial => name }.merge(options))
ensure
  self.template_format = old_format
end

Fíjate que no estamos sobreescribiendo el render :partial típico, es un helper simplemente. Para usarlo tendríamos que hacer algo como:

$('#some_div').html(<%=partial 'movie_information', :object => @movie %>);

En definitiva una forma mucho más cómoda, potente y simple de generar javascript desde el lado del servidor. Aunque insisto en que solo se debería de usar esta táctica para cosas triviales y pequeñas.

Comparando reales sin terminos naturales

Lo sé, el título no tiene mucho sentido, pero quería hacer una rima. Veamos una pequeña sesión en la consola de ruby

>> value = 69.99
=> 69.99
>> value * 100
=> 6999.0
>> value * 100 == 6999.0
=> false
>> a = value * 100
=> 6999.0
>> b = 6999.0
=> 6999.0
>> a.class == b.class && a.is_a?(Float)
=> true
>> print "#{a} es distinto a #{b} obviamente" unless a == b
6999.0 es distinto a 6999.0 obviamente
>> a.floor
=> 6998

Nada fuera de lo normal, ¿no?. ¿O si?.