Gobiernos digitales y lo que Argentina nunca será

Este blog está dedicado a temas de programación, generalmente de ruby o archlinux, pero hay cosas que deben ser mencionadas.

Siempre pensé que la digitalización de cuestiones en un gobierno pueden lograr la eficiencia del mismo, y lo más llamativo es que no se necesitan casi recursos. Actualmente es muy económico poner en linea una web con ciertas funcionalidades que pueden ahorrar millones y mostrar como se trabaja.

El ejemplo lo vi hoy en el diario la nacion y es la web SeeClickFix. Con solo ver el título se puede entender: “Reporte de tareas no urgentes”, no es ni mas ni menos que tener en una web la cosas que a los vecinos de una localidad le interesan resolver, no urgentes, y poder tenerlas organizadas para su resolución.

Uno se puede preguntar que tipo de cosas se podrian poner aca… simple, la poda de arboles, arreglo de calles, organizacion de cosas mal hechas, y un sin fin mas.

El único problema que esto plantearía es que en Argentina deberíamos cortar con la corrupción para gestionarlas, la burocracia, dejar de lado la ineptitud de mucha gente en las municipalidades, dejar de lado sus ganas de no-trabajar y su perdida de tiempo constante.

Considero que esto muestra lo que no podemos implementar en este país. Muestra mas como nuestra nación se asemeja mas a la parodia que hacia El Negro Olmedo con su país bananero.


Freaklances – Una serie que promete

No soy de los que recomiendan otras webs, generalmente porque no tengo mucho tiempo para andar mirando que recomendar, pero hoy cai en freaklances.blogspot.com y realmente promete ser muy buena.

El primer capitulo no lo fue tanto, pero el 2do no tiene desperdicio.

Espero la disfruten.


Lenovo G530 Tuchpad AlpsPS/2 ALPS GlidePoint

Hay veces que siendo usuario de linux desde hace ya mas de 2 años me encuentro con cosas que me hacen poner de los pelos. Desde hace 1 semana estoy usando este equipo, una Lenovo G530. Viene con un touchpad que linux lo reconoce bajo la identificacion de producto AlpsPS/2 ALPS GlidePoint.

Por algun motivo el cual desconzco, este touchpad en la version de kernel 2.6.31 de archlinux lo toma como mouse PS/2 generico, con lo cual no anda. Si pruebo deshabilitar el modulo psmouse y volver a hablitarlo, anda por al menos 5 segundos y deja de funcionar. Cosa que me pone peor, ya que eso demuestra que no es un problema de hardware sino de linux que lo reconoce mal.

Asi estoy, peliando a ver si puedo hacer que me deje de joder y ande de una vez por todas, es muy molesto tener que conectar un mouse usb todo el tiempo.

Esperemos pueda solucionarlo en el proximo rato.


Archlinux – Nginx – Passenger

Hace un tiempo comente que el server web Nginx tenia mejor rendimiento en varios test que consulte por internet, y buscando como configurarlo en la combinacion Archlinux + Nginx + Passenger encontre la mejor manera, lo cual demuestra que la gente que armo passenger realmente hizo un trabajo excelente.

La mejor forma de lograr esta combinacion es a travez de la gema Passenger:

sudo gem install passenger

Una vez que tenemos instalada la gema, ejecutamos:

passenger-install-nginx-module

El cual nos avisa si no tenemos nginx instalado la opcion de descargarlo y configurarlo, es la opcion que usaremos.

Al final nos da un ejemplo estandar para agregar una app:

server {
listen 80;
server_name www.example.com;
root path_to_app/public;   # <— be sure to point to ‘public’!
passenger_enabled on;
}

Y ya tenemos nuestra app en produccion con Archlinux + Nginx + Passenger.


Linea de comandos

Siempre  recuerdo mis comienzos en temas de computacion cuando tenia MS-DOS. A pesar que en estos tiempos no volveria a windows o cualquier sistema de microsoft, debo decir que esos comienzos con la linea de comandos para hacer cualquier cosa siempre los recorde con una sonrriza. El hacer todo por comandos y la potencia que daba eso, era algo que despues en un entorno grafico 100% terminaba aburriendo o haciendo las cosas mas lentas.

Es por eso, que al volver a la linea de comandos pero en estos tiempos debido a linux, me da muchas satisfacciones.

Ahora estoy trabajando con un par de pcs, y mediante SSH tengo que ir haciendo todas las cosas, como por ejemplo copiar archivos, zipearlos, levantar backups de bds y reestablecerlos en otros servers, etc. Les paso un pequeño resumen de los comandos mas usados:

  • Copia por SSH:

scp -r /path/to/origin /path/to/destiny

Con este comando copiamos el origin a destiny, incluyendo todos los subdirectorios (opcion -r).

  • Compresion y Descompresion de archivos

tar -cvvzf archivo.tar.gz /path/to/origen_a_comprimir

Comprime en el archivo archivo.tar.gz la ubicacion /path/to/origen_a_comprimir

tar -xvvzf archivo.tar.gz /path/to/ubicacion_donde_descomprimir

Con esta linea descomprimimos archivo.tar.gz en /path/to/ubicacion_donde_descomprimir

  • Backup y restore de base de datos por linea de comandos

mysqldump -h localhost -u username -p database_name > backup_db.sql

Hacemos el backup de database_name con el user username, host hostname en el archivo backup_db.sql

mysql -u [uname] -p[pass] [db_to_restore] < [backupfile.sql]

Reestablecemos a db_to_restore el sql que contiene backupfile.sql

Espero que sirvan estas pocas lineas como referencia rapida.


Render de errores en Rails

Algo llamativo es como Rails hace el render de errores en las vistas, agregandole un DIV a cada campo con error. Esto produce en muchos casos que se rompa como uno tiene armado un form.

Para solucionarlo, en environment.rb, hay que poner el siguiente codigo para que en lugar del DIV, utilice un SPAN:

ActionView::Base.field_error_proc = Proc.new {
  |html_tag, instance| "<span class=\"fieldWithErrors\">#{html_tag}</span>"
}

Ruby e IRC

Desde hace mucho tiempo que quiero armar un pequeño y simple programa para gestionar las descargas desde canales de IRC.

En IRC las descargas son po DCC (Direct Client-to-client), segun wikipedia, la definicion seria:

Es un protocolo de IRC que permite interconectar dos peers (puntos) usando un servidor IRC como saludo (handshaking) para permitir intercambiar archivos o llevar acabo tareas no relacionadas con el chat. Una vez conectados, una típica sesión de DCC corre independiente del servidor IRC. Originalmente diseñado para ser usado con IrcII es ahora soportado por varios clientes IRC.

Mediante este protolo y la utilizacion del comando SEND, se puede hacer transferencias de archivos.

DCC SEND

El servicio de envío (SEND) permite a los usuarios enviarse archivo entre ellos. La especificación original para el saludo (handshake) no permitía al receptor conocer el tamaño total del archivo, pausar y reanudar (resume) la transferencia. Esto hizo que los clientes introdujeran sus propias extensiones para el saludo (handshake), muchas de las cuales lograron un amplio soporte.

El saludo (handshake) original consistía que el emisor enviaba el siguiente CTCP al destinatario:

DCC SEND <filename><ip><port>

Como en el DCC Chat, <ip> y <port> son la dirección ip y el puerto de la máquina emisora donde escuchara la conversación entrante. Esta es una practica común el agregar el tamaño del archivo como último argumento.

DCC SEND <filename><ip><port><file size>

En este punto, la especificación original tenía al receptor conectado a la dirección dada y el puerto esperando los datos, o ignorar el pedido, pero para clientes que soportan la extensión DCC RESUME, una tercer alternativa es preguntar al remitente saltarse una parte del archivo enviando un CTCP reply:

DCC RESUME <filename><port><position>

Si el cliente soporta DCC RESUME, este responderá con un

DCC ACCEPT <filename><port><position>

y el receptor puede conectarse a la dirección y al puerto dato y escuchar los datos para añadirlo en el archivo.

Los datos se envían en bloques, a los que el cliente debe corresponder enviando los tamaños de los bloques de datos entrantes como enteros de 32 bits (network byte order). Esto ralentiza las conexiones, y es redundante porque tal comportamiento ya está implementado por TCP. La extensión send-ahead solventa este problema no esperando las respuestas, pero ya que el receptor aún debe enviarlas por cada bloque que recibe, en el caso de que el emisor las espere, no está completamente solucionado.

En algunos canales de IRC, hay pequeños scripts que van publicando archivos, y mediante algunas reglas se los puede ir solicitando.

Hasta aca muy clara la informacion, pero al momento de empezar a hacer algunas pruebas sobre Ruby, me encontre con el primero problema.

¿Como nos conectamos con el servidor irc mediante un script ruby?

Para esto vamos a usar la clase TCPSocket y mediante las simples lineas a continuacion, ya estamos conectados.

@socket = TCPSocket.new(servidor, puerto)

Una vez conectados, segun el RFC1459 que describe la arquitectura de IRC, tenemos que hacer el paso de registrarnos con el servidor, es decir, enviar la informacion necesaria para que sepa quienes semos, tanto ese servidor, como el resto.

Esto se logra mandando 3 datos: PASSWORD, NICK, USER. Cualquier operacion que se desee hacer antes de tener una registracion valida, nos va a dar un error.

Para esto usamos el siguiente codigo:

password  = "passwordsecreta"
nick      = "NickEnElServer"
@socket.puts "PASSWORD #{password}"
@socket.puts "NICK #{nick}"
@socket.pust "USER #{nick} #{nick} #{nick} :#{nick}"

No es mayor problema esta parte de conexion y resgitracion, pero despues de un rato importante, y revisar algunos codigos, vi que en algunos casos, enviaban un sleep despues de la accion USER. Esto es para no enviar nada antes que el servidor nos registre, algo tan simple como esto:

sleep 1

Una vez que estamos registrados, podemos seguir enviando comandos varios al server.


AutoComplete en IRB

Cuando se empieza a programar con Ruby, es muy comun hacer pruebas o verificar scrips en la consola IRB.

Si anteriormente se uso el script/console de rails, algo que uno no tiene seteado al momento de usar IRB es el autocomplete. Para que tengamos esto debemos crear el archivo .irbrc en nuetro perfil con el siguiente codigo:

IRB.conf[:AUTO_INDENT] = true
IRB.conf[:USE_READLINE] = true
IRB.conf[:LOAD_MODULES] = [] unless IRB.conf.key?(:LOAD_MODULES)
unless IRB.conf[:LOAD_MODULES].include?('irb/completion')
  IRB.conf[:LOAD_MODULES] << 'irb/completion'
end
# load libraries
require 'rubygems'
require 'wirble'
# start wirble (with color)
Wirble.init
Wirble.colorize
#Irb History to file, all session is save to ~/.irb-history
module Readline
  module History
    LOG = "#{ENV['HOME']}/.irb-history"
    def self.write_log(line)
      File.open(LOG, 'ab') {|f| f << "#{line}\n"}
    end
    def self.start_session_log
      write_log("# session start: #{Time.now}\n")
      at_exit { write_log("# session stop: #{Time.now}\n") }
    end
  end
  alias :old_readline :readline
  def readline(*args)
    ln = old_readline(*args)
    begin
      History.write_log(ln)
    rescue
    end
    ln
  end
end
Readline::History.start_session_log                                                                               

# Quick benchmarking
def quick(repetitions, *blocks)
  require 'benchmark'
  Benchmark.bmbm {|b|
    blocks.each {|block|
      b.report {repetitions.times &block}
    }
  }
  nil
end                                                                                         

def reset_irb()
  exec $0
end                                    

def split(array)
  length = (array.length / 3.0).ceil
  [array[0, length], array[length, 2*length], array[2*length, 3*length]]
end                                                                                                                                        

class Object
  # Return only the methods not present on basic objects
  def exclusive_methods
    methods_array = (self.methods - Object.new.methods).sort
    length        = methods_array.length
    col           = 4
    inicio        = -1
    arr           = []
    while inicio < length do
      arr << methods_array.slice(inicio+1..inicio+col)
      inicio += col
    end
    arr_final = []
    arr.each do |subarr|
      str = String.new
      subarr.each do |elemento|
        str_spaces = ""
        elem=(30-elemento.length).times {str_spaces+=" "}
        str << "#{elemento}#{str_spaces}"
      end
      arr_final << str
    end
    puts arr_final
  end
end                                                                                                                                        

module Kernel
  def r(arg)
    puts `ri "#{arg}" -f ansi`
  end
  private :r
end                                                                                                                                        

class Object
  def puts_ri_documentation_for(obj, meth)
    case self
    when Module
      candidates = ancestors.map{|klass| "#{klass}::#{meth}"}
      candidates.concat(class << self; ancestors end.map{|k| "#{k}##{meth}"})
    else
      candidates = self.class.ancestors.map{|klass|  "#{klass}##{meth}"}
    end
    candidates.each do |candidate|
      puts "TRYING #{candidate}"
      desc = `ri '#{candidate}' -f ansi`
      unless desc.chomp == "nil"
      # uncomment to use ri (and some patience)
      #desc = `ri -T '#{candidate}' 2>/dev/null`
      #unless desc.empty?
        puts desc
        return true
      end
    end
    false
  end
  private :puts_ri_documentation_for                                                                                                      

  def method_missing(meth, *args, &block)
    if md = /ri_(.*)/.match(meth.to_s)
      unless puts_ri_documentation_for(self,md[1])
        "Ri doesn't know about ##{meth}"
      end
    else
      super
    end
  end                                                                                                                                      

  def ri_(meth)
    unless puts_ri_documentation_for(self,meth.to_s)
      "Ri doesn't know about ##{meth}"
    end
  end
end                                                                                                                                        

RICompletionProc = proc{|input|
  bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
  case input
  when /(\s*(.*)\.ri_)(.*)/
    pre = $1
    receiver = $2
    meth = $3 ? /\A#{Regexp.quote($3)}/ : /./ #}
    begin
      candidates = eval("#{receiver}.methods", bind).map do |m|
        case m
        when /[A-Za-z_]/; m
        else # needs escaping
          %{"#{m}"}
        end
      end
      candidates = candidates.grep(meth)
      candidates.map{|s| pre + s }
    rescue Exception
      candidates = []
    end
  when /([A-Z]\w+)#(\w*)/ #}
    klass = $1
    meth = $2 ? /\A#{Regexp.quote($2)}/ : /./
    candidates = eval("#{klass}.instance_methods(false)", bind)
    candidates = candidates.grep(meth)
    candidates.map{|s| "'" + klass + '#' + s + "'"}
  else
    IRB::InputCompletor::CompletionProc.call(input)
  end
}
Readline.basic_word_break_characters= " \t\n\\><=;|&"
Readline.completion_proc = RICompletionProc

Hice un update de la idea, ahora con la gema Wirble se puede tener colores en los resultados que va mostrando en las operaciones.
El segundo update es para que cada sesion que hacemos sobre IRB la pase a un archivo automaticamente, lo cual nos sirve para despues tomar ese codigo para alguna otra parte donde querramos usalo, dicho archivo se ubicara en ~/.irb-history

El script de history lo tome de aca.

En el proximo post voy a armar para poner mi configuracion de VIM, git y un par de cosas mas que uso dia a dia para poder desarrollar sobre rails y una pequeña y simple configuracion de Nginx sobre ArchLinux que desde hace tiempo tengo ganas de probarlo.

PD: Todo muy lindo hasta que te cruzas con configuraciones adicionales que las hizo algun craneo [pueden verlas aca]


Unit Tests con FactoryGirl

Uno de los grandes temas que tuve que implementar junto con los test, fue crear objetos de mis modelos para las pruebas. El gran problema que me encontre, fue cuando en los modelos las relaciones entre ellos se vuelven muy rebuscadas.

Pongamos un ejempo para entenderlo, dados los siguientes modelos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Estudiante <ActiveRecord::Base
  has_many :cursada
  validates_presence_of :cursada
end
class Cursada < ActiveRecord::base
  belongs_to :estudiante
  belongs_to :profesor
  validates_presence_of :estudiante
  validates_presence_of :profesor
end
class Profesor < ActiveRecord::Base
  has_many :cursada
  validates_presence_of :cursada
end


El gran problema es que para crear una Cursada, hay que tener un Estuiante y un Profesor creados, pero a su vez, para crear cada uno de estos, tenemos que tener una Cursada ya creada. Dandose una superposicion de necesidades.

Para resolver esto desde factory girl podemos hacer lo siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Factory.define :cursada, :default_strategy => :build do |curso|
  curso.estudiante nil
  curso.profesor nil
end
Factory.define :estudiante, :defaut_strategy => :build do |estudiante|
  estudiante.cursadas do |cursada|
    [cursada.association(:cursada)]
  end
end
Factory.define :profesor, :defaut_strategy => :build do |profesor|
  profesor.cursadas do |cursada|
    [profesor.association(:cursada)]
  end
end

Pero a pesar de esta ser la unica solucion que encontre dando vueltas, solo pude generar los objetos con un setup del TestCase y crear los objetos necesarios con llamadas a build en lugar de create para que no valide hasta que yo este seguro que las asociaciones son correctas.

Un ejemplo seria:

1
2
3
4
5
def setup
  @estudiante=Factory.build(:estudiante)
  @profesor=Factory.build(:profesor)
  @cursada=Factory.create(:cursada, :estudiante => @estudiante, :profesor => @profesor)
end

De esta forma para mis TestCase tengo definida un objeto @cursada que valida el save general, despues puedo ir cambiando sus atributos para corregir comportamiento para un test en particular.

Si alguien resolvio de una mejor manera este problema, se agradecera cualquier informacion.


Ruby on Rails :: Unit Testing

Un pequeño y tonto error al momento de hacer unit testing:

Si estamos en un proyecto que esta avanzado en su desarrollo pero no en su testeo, nos vamos a encontrar que al momento de crearlos tenemos que crear dos archivos para cada modelo:

  • Fixture
  • Unit Test

Los archivos necesarios tienen este formato:

  • Ficture: /test/fixtures/modelo.yml (importante: el nombre del modelo debe ser como figura en la base de datos, si tenemos la regla de inflector para pluralizarlo o tomar un nombre en particular como puede ser person => people, nuestro fixture sera people.yml)
  • Unit Test: /test/unit/modelo_test.rb (el nombre sera igual que como figura el modelo, para el ejemplo anterior tendriamos person_test.rb)