jueves, 16 de julio de 2009

Ruby RAII

RAII (Resource Acquisition Is Initialization) es una técnica aplicable en muchos lenguajes de programación como C++ y los lengujaes .net que sirve para asegurar que la liberación de un recurso siempre se llevara a cabo al cerrarse un bloque de código sin importar que evento ocurrise (retorno de una funcion, excepcion, etc...). Ruby por supuesto que cuenta con esta posibilidad a través del uso de métodos con bloques de código (palabra clave yield)

He aqui un ejemplo:


#
# La clase X tiene un metodo open para inicializar (open)
# Y uno para cerrar, seria una tragedia si el metodo open
# se invocara y no se invoque el close correspondiente al final
#
#
class X
def open( argument1, argument2 )
print "open with argument1=#{argument1} and argument2=#{argument2}\n"
end

def operation1
print "running operation1\n"
end

def operation2
print "running operation2\n"
end

def close
print "closing\n"
end
end


#
# Mejor usar RAII
#

class X
def self.open( *args )
x_instance = X.new
x_instance.open( *args )
begin
yield(x_instance)
ensure
x_instance.close
end
end
end


#
# Y se usa asi
#
X.open( "arg1", "arg2" ) do |x|
x.operation1
x.operation2
end




Espero que os haya iluminado

martes, 23 de junio de 2009

NilClass horror

Un horror




# el nil class es la clase de la cual nil es instancia
class NilClass
# todo metodo desconocido que es invocado sobre el nil
def method_missing(method_obj,*args)
method_obj.to_s
end
end

print nil.koiiiewiiriieiw,"\n"

print @oooooooooooooooooooooo.blahhhhhhhhhhhhhhhhhhhhhhhhh,"\n"
print @ewewewwwewo.dakishimetakokoronokusumo,"\n"

# un horror
print $uqhwuiqwhrqrqwrkjwqhrjkqwhrqwkjrhqwrjkwqrhkqwrjqwrj.l,"\n"



Un horror

domingo, 21 de junio de 2009

Comparacion de rangos

Es muy común al programar, encontrarse con la necesidad de verificar algún rango de algo:


# la manera "dificil"
if a > 3 and a < 9 then
print "a esta entre 3 y 9\n"
end


Mejor asi, usando el operador ===


# la manera "canchera"
if (3..9) === a then
print "a esta entre 3 y 9\n"
end


Como si esto fuera poco, el operador === tiene todos los usos que uno se pueda imaginar, como por ej, para verificar si un texto matchea una expresion regular:


# la manera "canchera"
if /^ruby/ === txt then
print "'#{txt}' tiene ruby al principio\n"
end


Y si se les da la gana, pueden usar este operador en sus propias clases (también obviamente definirlo o redefinirlo para la clase existente que quieran)



class X
def ===(a)
print a,"\n"
end
end

viernes, 5 de junio de 2009

Ruby hooking

Les traigo un truco que los asombrara... con una tenica de hooking aplicada al ruby para poder enganchar los metodos que quieran de cualquier objeto y controlar su ejecucion, asi como registrar llamados a ese metodo , filtrar cosas, etc.

Aca el module q lo hace posible:

hooking.rb


module Hook
def hook( method_name, hook_name = nil, old_method_name = nil)

obj = self

# si no se le pasa el nombre de la funcion que controla el hook
# arma un nombre de funcion
hook_name ||= "#{method_name}_hook"

#lo mismo con el nombre de la variable de instancia
# que almacena la referencia al metodo original
old_method_name ||= "__old__#{method_name}"

# almacenar el metodo original
eval("@#{old_method_name} = self.method( method_name.to_sym)")

# redefinir el metodo para que invoque el metodo de hook, pasandole
# un bloque de codigo que ejecute el metodo original, entonces el metodo
# de hook puede invocar al metodo original usando yield
eval("
def obj.#{method_name}(*x)
self.#{hook_name}(@#{old_method_name},*x) do |*x|
yield(*x) if block_given?
end
end
")

end
end

class Object
# includir el modulo de Hook en Object para que se pueda aplicar a todo Object
include Hook
end



Y ahora un pequeño ejemplo de como podria usarse

main.rb


require "hooking"

class X

def foo( num )
print "metodo foo invocado con num = #{num}\n"
end

def bar
print "metodo bar invocado\n"
[1,2,3].each do |x| yield(x) end
end

end

x = X.new

x.hook(:foo)

def x.foo_hook( foo_original, num )
print "foo invocado\n"

# se invoca al metodo original, pero alterando los parametros
foo_original.call( num+1)

print "fin de foo\n"
end

x.hook :bar
def x.bar_hook( bar_original )

print "bar invocado\n"

bar_original.call do |x|
# tambien se puede alterar y controlar
# el uso de yield del metodo
yield(x+2)
end

print "fin de bar\n"
end


x.foo(3)
x.bar do |x|
print x,"\n"
end

martes, 21 de abril de 2009

Programacion ruby EN un celular :p


No pude evitar observar la palabra clave del ruby "def" (se usa para DEFinir metodos en ruby) en una de las teclas del celular, asi que imagine: esto esta pensado para programadores de ruby, en seguida me puse a pensar como seria programar EN un celular:





# para pner cmtrios ay q scrbrlos tods asi
# est mtodo c pue d usr cmo print
def abc(ghi)
print ghi,"\n"
#porq noay na tcla cn "end" en l celu?
end
abc "hla mndo!"
abc "cmo ests"

domingo, 15 de marzo de 2009

Aprendiendo git-svn en 5 minutos

Este finde estuve viendo las posibilidades que tiene git-svn, nunca use git pero me llamo mucho la atención el manejo que tiene de múltiples repositorios, cuya primera utilidad que le vi es poder trabajar "offline", es decir, sin acceso al repositorio central, y mantener la granularidad de los commits ya que se puede commitear al repositorio "local" cuantas veces se quiera hasta que en un momento se mandan todos los commits en un "push". En el caso de git-svn, se pueden visualizar y analizar en los logs del servidor SVN cada uno de esos commits como si hubiese mandando cada uno de ellos de manera "normal". git-svn también puede ser de agrado para los fanáticos de git cuando se vean forzados a trabajar con un repo svn y seguramente tiene un sin-fin de utilidades mas.

Actualizacion: Usuarios de svn pueden aprender git de una manera muy facil en Git - Svn Crash Course


Lo primero y principal para utilizar esta herramienta es instalarla, yo que uso fedora, me basto con:


yum install git-svn


Seguramente, para los usuarios de debian y afines sera suficiente (corrijanme si me equivoco):


apt-get install git-svn


Posteriormente, se aprende como utilizar la herramienta para clonar un repositorio SVN para los usuarios de git, o "checkautear" usando git, para los usuarios de svn:


git-svn clone $URL


Donde $URL es la url completa del servidor svn como "file:///usr/srv/svn/proyecto" o "http:///www.websvn.com/svn/proyecto", lo que hace el comando, es crear una copia local del repositorio SVN, al estilo de git, esto equivale al checkout de svn y por lo tanto solo debe hacerse la primera vez, obviamente es necesario tener acceso al repositorio para poder hacer esto

A partir de haber clonado el repositorio, ya se puede trabajar con el repositorio local, para los que sean usuarios de git es simple: es lo mismo que en git (guarda al final que no se pushean los cambios de la misma manera), y para los que no conocen el maravilloso mundo de git, también es sencillo, simplemente hay que ejecutar el siguiente comando con cada commit:


git commit archivo -m 'mensaje'


El comando es igualito al de svn, pero tengan presente de que este comando "commitea" solo al repositorio local, el que se clono al principio, asi mismo NO requiere acceso al repositorio ni ninguna conexión con el, pueden hacer este commit todas las veces que hagan faltan sin necesidad de contactar al repositorio.

Cuando logran conexión con el repositorio o cuando lo crean conveniente, llega la hora de hacer el "push" (mandar todos los commits que se hicieron local al repositorio central), el comando el siguiente:


git-svn dcommit


Cuando ejecuten el comando, verán como git-svn manda cada commit que se efecto localmente desde la que se clono el repo o se hizo el ultimo dcommit, y lo mas importante, lo que da todo el sentido a esto: a cada commit que efectuaste con "git commit", le corresponde UN commit de svn que puede analizarse y verse en los logs del servidor svn por cualquier otro usuario y con las herramientas svn clásicas.

Bueno, esto fue git-svn para Fedora 32 y espero que les haya gustado. Chau!!!