Dagi3d v4

¿Fin del spam?

Gracias al consejo del señor Yanes, me animé a probar el servicio que ofrece Google que nos permite utilizar el sistema de correo de Gmail utilizando nuestro propio dominio. Pero lo interesante de esto no es el hecho de poder contar con la interfaz web de Gmail para leer el correo donde queramos(que también podría serlo), si no el poder descargar con nuestro cliente habitual el correo almacenado en los servidores de Google y utilizar su filtro anti-spam que funciona muy bien y así minimizar en la medida de lo posible el coñazo que supone el correo basura. De momento, salvo un falso positivo, me está funcionando mucho mejor que el sistema que lleva Thunderbird integrado que se tragaba unos cuantos correos vende rolex/viagras/hipotecas/titulos falsos, aunque en parte es lógico, porque siempre irá mucho mejor un filtro bayesiano entrenado por 50 millones de usuarios que otro por uno solo...

Google Apps: http://www.google.com/a/

vi.sualize.us, el del.icio.us para las imágenes

Hace poco salió a la luz vi.sualize.us, un marcador social enfocado a las imágenes que nos permite organizar las fotos que vamos encontrando por internet utilizando etiquetas y compartirlas si queremos. Vamos, que sería el equivalente a del.icio.us  para imágenes y la verdad es que la aplicación tiene bastante buena pinta.

El proyecto ha sido desarrollado en exclusiva por Victor Espigares y también ha contado con la colaboración de ­Sergi Meseguer para la creación de la ­extensión para firefox(todavía en fase beta)


­

Programa de facturación en Ruby On Rails

Hace poco para optar a un trabajo tuve que realizar como prueba una aplicación en Rails que gestionase un listado de facturas junto a sus clientes. El caso es que decidí añadirle alguna cosilla más y hacerle una interfaz más aceptable y liberar el código por si a alguien le podía interesar.
La aplicación puede exportar a pdf(aunque hace falta java para esto) y el diseño del pdf es totalmente personalizable a partir de un documento xhtml y css.
De momento no tiene mucha cosa, pero la idea es utilizarlo e irlo ampliando conforme lo vaya necesitando ahora que empiezo con el tema del freelanceo.

Se puede ver en funcionamiento en http://facturails.dagi3d.net/ y se puede descargar directamente desde el repositorio subversion en http://svn.dagi3d.net/rails/facturails/trunk (bajo licencia MIT)

Sumando varios elementos de un array

Realizando una aplicación en Rails necesitaba sumar varios atributos de los objetos almacenados en un array. El problema es que cuando se trata de sumar un único atributo, se suele utilizar el método inject:

total = mi_array.inject { |sum, obj| sum + obj.value }

pero en este caso no me terminaba de convecer estar llamando al método inject tantas veces como atributos quisiera sumar, así que en teoría la solución pasaría por iterar sobre el array e ir sumando:

var1 = 0
var2 = 0
var3 = 0
...
mi_array.each do |obj|
  var1 += obj.value1
  var2 += obj.value2
  var3 += obj.value3
  ...
end

Funcionar, funcionaba, pero digamos que el código quedaba algo feo, así que para seguir trasteando, intenté encontrar una solución más 'ruby' y esto fue lo que hice:

class Array
  
  def accumulate(fields)
    
    results = fields.dup
    
    self.each do |obj|
      fields.each_key do |key|
        results[key] += obj.send(key) if obj.respond_to?(key)
      end
    end
    
    results
  end
end

Ahora bastaba con llamar al método accumulate sobre el array de objetos e indicar qué atributos quería sumar para obtener un hash con los resultados:

# la lista de objetos
foos = [
  OpenStruct.new(:foo => 1, :bar => 2, :foobar => 3),
  OpenStruct.new(:foo => 3, :bar => 4, :foobar => 5),
  OpenStruct.new(:foo => 5, :bar => 6, :foobar => 7)
]

foos.accumulate(:foo =>­; 0, :bar => 0, :foobar => 0) 
# {:foo=>9, :bar=>12, :foobar=>15}­

Comparar gemas instaladas en desarrollo y producción

A raíz de un post en el blog de Nicolás Orellana, donde mencionaba el problema de no tener sincronizadas las gemas instaladas en la máquina de desarrollo con las que deberían estar también en la máquina de producción, me animé a escribir una pequeña tarea para Capistrano que intentase resolver este problema. La idea en principio era sencilla, tan sólo habría que obtener la lista de gemas instaladas en local utilizando el comando 'gem list' tal como mencionaba Nicolás, hacer lo mismo en remoto, compararlas para ver las diferencias y luego ofrecer la posibilidad de instalar aquellas que no estuviesen en la máquina de producción.

Y esta fue la solución a la que llegué (de momento no hace ningún control sobre las versiones, pero si tengo un rato intentaré completarla):

task :compare_gems do
  
  def parse_gem_line(line, gems)
    if line =~ /^([[:alnum:]]+)\s\((.*)\)/
      gem = $1
      gems[gem] = []
      versions = $2.gsub(/\s/, '').split(",")
      gems[gem] << versions
    end
  end
  
  local_gems = {}
  remote_gems = {}
  
  local_gem_list = %x{gem list}
  local_gem_list.each_line { |line| parse_gem_line(line, local_gems)}

  run "gem list" do |channel, stream, data|
    parse_gem_line(data, remote_gems)
  end
  
  not_installed_gems = local_gems.dup
  
  not_installed_gems.delete_if {|key, value| remote_gems.has_key? key }
  
  puts "== Not installed gems =="
  
  not_installed_gems.each_key do |gem|
    
    puts "* #{gem}"
    puts "Install? [yN]"
    answer = STDIN.gets.chomp
    
    if answer.downcase == "y"
      run "gem install #{gem} -y" do |channel, stream, data|
        puts data
        if data =~ /^>/
          install_option = STDIN.gets.chomp
          channel.send_data "#{install_option}\n"
        end
      end
    end
  end
  
  puts "========================"
end