4 Trabes

¿Quieres trabajar en Trabe Soluciones?

Publicado por el Sábado, 12 de Abril de 2008

Trabe Soluciones está creciendo. Ahora que nos vamos a mudar a unas oficinas más amplias tenemos una vacante. La oferta de trabajo que estamos distribuyendo es la siguiente.

Buscamos personas para trabajar en A Coruña.Trabe te necesita

Nos gustaría que supieses desarrollar aplicaciones web MVC con J2EE y Ruby on Rails, que controlases de HTML, CSS y Javascript, que tuvieses conocimientos de diseño gráfico, que administrases servidores, que te sintieses cómodo en Linux, que te gustase usar software libre,...

Si esto te describe ven corriendo. En caso contrario, no te preocupes, valoramos la experiencia que tengas, pero también nos interesa tu pasión y tus ganas de aprender, de trabajar de una manera diferente, de asumir responsabilidades y de crecer con nosotros.

Te ofrecemos unas excelentes condiciones. Todo lo que te ofrecen el resto de ofertas de trabajo y mucho más: horario flexible, oficina céntrica(nada de polígonos), plantilla joven, café a media manaña, no llevamos corbata ni traje... Nos importa tu calidad de vida.

Si quieres saber más de nosotros, puedes echar un vistazo a nuestra web (http://www.trabesoluciones.com) o a nuestro blog (http://4trabes.com), o directamente contactar con nosotros para plantearnos cualquier duda (contacto@trabesoluciones.com).

Esperamos tu curriculum en rrhh@trabesoluciones.com.

Ya han llegado los primeros CVs. ¿A qué esperáis para enviar el vuestro?

The Overlooked Power of Javascript

Publicado por el Viernes, 11 de Abril de 2008

Siempre he pensado que el lenguaje Javascript es uno de esos pequeños infiernos con los que uno aprende a convivir. Debo confesar que mi relación con este pequeño gran lenguaje de programación ha cambiado de manera brutal desde que conozco Prototype. Desde esta posición, me ha llamado mucho la atención la charla de Glenn Vandeburg The overlooked power of Javascript (que puede verse y leerse en InfoQ).

Building tigth enforced encapsulations and APIs ands contracts that must be follow, placing restrictions, enforcing rules, drawing boundaries, and working with C++ and then Java trained us to think in terms of this kind of power, and I’m not saying it’s bad, but I’m saying that if that’s yours perspective of power, Javascript is going to look like a toy. Everything is open. You practically can’t build any walls around anything in Javascript.

Creo que en esta reflexión en voz alta (que no curso o tutorial), Glenn ha reflejado a la perfección la relación que la mayor parte de los programadores criados en el mundo Java tenemos con Javascript y por qué deberíamos cambiarla. Una charla muy recomendable para críticos, defensores, fanáticos, indecisos, conversos, pasotas y toda clase de moderados y extremistas.

Google Chart API + ruby = gchartrb

Publicado por el Martes, 01 de Abril de 2008

En nuestro último proyecto necesitamos incluir varios tipos de gráficas (líneas, barras y alguna tarta). De entre las múltiples posibilidades existentes hemos decidido usar el API de gráficas de Google (Google Chart API) que nos ofrece un montón de posibiliades de manera sencilla, fiable, gratuita e ilimitada. La única peculiaridad de su uso es que los datos a representar deben ser codificados antes de enviarlos al servidor de gráficas. Esto no representa mayor problema, menos aún cuando existen varios wrappers distribuidos como gemas o plugins que hacen este trabajo por nosotros, como son: gchartrb, Googlecharts o Google Charts on Rails.

Nosotros estamos usando gchartrb, porque entendemos es la más completa y documentada y porque su API nos agrada más. Por ejemplo, para pintar una sencilla gráfica como la que sigue…

... necesitamos un código como este:

PIE_COLORS = %w(9bd500 a4d520 b0d54b bbd575 c7d5a0)

data = Post.count(:group => :user_name, :order => 'count_all desc')

pie_chart = GoogleChart::PieChart.new('300x100') do |chart|
  data.each_with_index do |row, i| 
     chart.data "#{row[0]} (#{row[1]})", row[1], PIE_COLORS[i]
  end 
end 

image_tag pie_chart.to_url

Grandes descubrimientos de nuestro tiempo: Si true entonces true, sino false

Publicado por el Jueves, 21 de Febrero de 2008

var isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;

Pero qué co…

¿Por qué lo llaman Firebug? (cuando quieren decir... Firebug)

Publicado por el Miércoles, 13 de Febrero de 2008

Imagino que conoceréis Firebug. Es una maravillosa extensión del Firefox que permite desarrollar páginas web de una manera antes jamás soñada :D.

Con el Firebug podemos inspeccionar los valores de las propiedades CSS, los valores calculados por el navegador, depurar Javascript… vamos, que es una herramienta indispensable para desarrollar.

Por otro lado, no sé si sólo nos pasa a nosotros, pero últimamente (me refiero a un últimamente largo, algo así como ¿un año?), el Firefox se está convirtiendo en una especie de monstruo tragamemoria un tanto inestable (es posible que se deba a que lo estamos ejecutando en una Fedora de 64 bits… o a que esté cargado de extensiones… o a muchas otras cosas, es posible). La cuestión es que a veces abres una página y el Firefox decide cerrarse, y lo hace cada vez que intentas visitar esa página (¿tal vez algún plugin quisquilloso o una extensión remilgada?). Y otras veces dice que sí, que ha cargado con éxito una página, pero sigue enseñando la página anterior…

Este último comportamiento es especialmente odioso cuando estás desarrollando una aplicación web: “cambio esto aquí, toco allí, y debería salir esto… a ver a ver, F5… ¿no sale? mmm Claro, claro, toco aquí, le doy allí, un poco más por acá… F5… ¿ein? background: red; color: lime;... F5… ¬_¬U”. En ese momento caes en la cuenta de que, ¡oh!, ¡pero si la acción se ejecuta en el servidor! ¡Los valores cambian en base de datos! ¡Es el Firefox que no te quiere enseñar la página! Así que lo cierras, lo vuelves a abrir, y ahora sí: los cambios están ahí. Después de todo sabías lo que hacías.

Pues bien, parece que este comportamiento se debe al Firebug (al menos en nuestros equipos), y hay otra solución además de cerrar y ejecutar de nuevo el Firefox: si tienes activo el Firebug, lo minimizas y lo vuelves a mostrar (o al revés) y ¡la página con todos los cambios aparece por arte de birlibirloque! (en este momento no sabría decir qué sucede cuando lo desactivas directamente…).

Ahora entiendo que lo llamen Firebug.

YAML: un framework CSS

Publicado por el Jueves, 31 de Enero de 2008

Hacía ya mucho, mucho tiempo de mi último post, y David, el único de nosotros que parece lo suficientemente disciplinado como para escribir con alguna regularidad, había empezado a monopolizar este blog, así que aquí estamos de nuevo…

En general, los frameworks CSS consisten en una serie de ficheros CSS que han de ser enlazados por nuestras páginas y que proporcionan, entre otras cosas:
  • Reseteo del navegador: los navegadores disponen de una hoja de estilos que define el estilo “por defecto” de las páginas que renderizan. Para evitar las diferencias entre navegadores y simplificar la tarea de desarrollar para múltiples navegadores se incluye una hoja de estilos que “anula” los estilos por defecto.
  • Tipografía y estilos básicos: se fijan también algunos valores para la tipografía y algunos elementos HTML básicos (formularios, encabezados, párrafos, etc.).
  • Layout o grid: a la hora de posicionar los elementos en pantalla, hay dos opciones: o bien utilizar una serie de layouts predefinidos por el framework, o bien posicionar elementos en un grid montado mediante CSS.
  • Hacks o patches: para garantizar que todo se ve como debe en el IE o en otros navegadores.
  • Plugins: algunos frameworks ofrecen la posibilidad de añadir plugins, que no son más que ficheros CSS adicionales y, ocasionalmente, imágenes de fondo, para crear determinados widgets como menús con tabs, formularios “chulos”, etc.

Existen multitud de frameworks CSS: Yahoo Grids CSS, Blueprint, Elements, Logicss, Schema, WYMstyle.

Nosotros hemos optado por YAML, y no porque su nombre nos suene rubyistico, que no somos de esos, sino porque, aparte del framework de Yahoo, es el que parece tener una documentación más amplia y, sobre todo, más útil (os la recomiendo como lectura, aunque no vayáis a usar el framework). Eso sí, también es de los que tiene un mayor número de ficheros y al principio resulta un poco complejo.

Como colofón, ya que parece que está de moda en este blog ponerse literarios, ahí va lo mío: Car tout ce que je raconte, je l’ai vu; et si j’ai pu me tromper en le voyant, bien certainement je ne vous trompe point en vous le disant. He dicho.

Haml ¿Haiku?

Publicado por el Lunes, 28 de Enero de 2008

Lo prometido es deuda: un nuevo post. Hoy: Haml. ¿Comparte realmente las características de un buen haiku?, ¿es breve, conciso, evocador, bello, etc?.

Nota: Este post no va a explicar qué hace o cómo se usa Haml. Eso podéis descubrirlo ampliamente en su página web, que debéis visitar para poder seguir leyendo.

Admito que mi experiencia con Haml no es muy amplia. Hasta hace poco sólo había usado ERB y Markaby. Por lo que había leido del tema, Haml se me antojaba similar a Markaby, así que no le di mucha importancia hasta el día en que me tope de bruces con StaticMatic (del que hablaré en otro post… espero). De todos modos, y a pesar de mi corto rodaje me he dado cuenta de que Haml es la típica historia que, o bien odias, o bien amas con locura. Así que tenemos nueva batalla en el mundo Rails: hamelistas contra erebeistas (si nadie ha registrado esas palabras yo lo haré: quiero un euro cada vez que alguién las utilice, jaja..). En Trabe Soluciones, ante estos debates, solemos optar por la tercera vía (la llamada “vía gris”) que se basa en usar las cosas sólo cuando lo consideramos oportuno, sin que medien pasiones u odios.

Lo que nos gusta de Haml

  • Conciso. Muy conciso. Escribir poco es bueno
  • Genera un HTML bonito (bien indentado, etc)
  • SASS, que tiene cosas geniales como la aritmética de colores

Lo que nos disgusta de Haml

  • No todos los editores entienden Haml (y ésto es como “La Casera”, si no hay highlighting nos vamos)
  • A veces cuesta encontrar el fragmento de markup o de CSS que estamos depurando con herramientas como Firebug.
  • Es más lento que ERB
  • ¿Por qué demonios no se puede indentar con un tab y hay que usar dos puñeteros espacios? No importa mucho si el editor cambia los tabs por espacios, pero no puedo evitar recordar pesadillas “cobolisticas” de antaño
  • Convence tú a un diseñador para que lo aprenda

En resumen. Haml está ahí. Está bien pensado. Es útil. No es perfecto. Pero tendréis que probarlo para saber si se adapta a vuestras necesidades. Haml es, en efecto, como un haiku: algo breve cuya belleza es, a veces, discutible: Mujer agachada
que orina y hace fundir
la nieve

Generación dinámica de librerías Javascript internacionalizadas con GetText

Publicado por el Viernes, 31 de Agosto de 2007

La internacionalización es uno de los requisitos del proyecto que estamos desarrollando actualmente en Trabe Soluciones con Ruby on Rails. Para cumplirlo estamos utilizando GetText y Ruby GetText para la internacionalización de cadenas y código propio para internacionalizar ActiveRecord (un enfoque habitual cuando uno se enfrenta a este problema).

La aplicación además, cuenta con una adminsitración que, por su interfaz, utiliza una cantidad considerable de Javascript. Dicho Javascript también debe estar internacionalizado. Lo primero que se nos puede pasar por la cabeza es separar las cadenas que requieran traducción a unos ficheros separados y que nuestro layout enlace uno u otro en función del idioma de la petición (o el idioma preferido del usuario). Si lo hacemos así, estamos desaprovechando todas las ventajas que nos aporta el uso de GetText, en especial las facilidades para gestionar la traducción de cadenas (utilizando herramientas como poEdit).

Lo que vamos a hacer es generar los Javascripts dinámicamente utilizando Ruby embebido, como un rhtml cualquiera, con lo que podremos incrustar nuestras llamadas a GetText con total impunidad. Resumiendo, que lo que queremos es utilizar algo como ésto en nuestro layout:

   <%= javascript_include_tag "/dyn_javascripts/#{Locale.get}/application" 

Para ello necesitamos un poco de código.

Creamos un controlador que responda a las peticiones y que simplemente delegue en la vista correspondiente. Estas vistas estarán en la carpeta app/views/dyn_javascripts y tendrán la extensión .djs (por ejemplo).

class DynJavascriptsController < ApplicationController                

  layout false                

  def method_missing(symbol, *args)
    if symbol.to_s =~ /(.*)\.js$/ 
      render :action => $1
    end
  end  
end

Añadimos la ruta correspondiente al fichero de rutas (routes.rb). En ella pasamos el idioma como parametro porque nuestros filtros de GetText lo buscan en la URL, no por vicio.

map.connect 'dyn_javascripts/:language/:action.js', :controller => 'dyn_javascripts'

Ahora creamos un fichero que requeriremos al iniciar la aplicación (en el fichero environment.rb). Este fichero incluye una clase que procesa nuestras plantillas .djs y que debemos registrar con el métodod register_template_handler de ActionView::Base::. Además incluimos el código necesario para que la aplicación encuentre el controlador que hemos definido previamente (la última línea de código) de tal modo que se recargue con cada petición en modo desarrollo.

require 'erb'

module DynJavascripts  
  class View

    def initialize(action_view) #:nodoc:
      @action_view = action_view
    end

    def render(template, local_assigns={})
      @action_view.controller.headers["Content-Type"] = 'text/javascript'      
      @action_view.instance_eval { ERB.new(template).result(binding) }      
    end    

  end 

end

ActionView::Base::register_template_handler 'r_js', DynJavascripts::View

# Nuestro controladoe está situado en 
# lib/common/dyn_js/dyn_javascripts_controller.rb
Dependencies.load_paths << "#{RAILS_ROOT}/lib/common/dyn_js" 

Hecho todo esto ya podemos escribir código simpático como el siguiente en nuestra carpeta app/view/dyn_javasctripts:

# Archivo app/views/dyn_javascripts/application.djs
function changeALink(whichLink) {
    var the_link = document.getElementById(whichLink);
    the_link.href =  "<%= url_for :controller => 'a_controller'  %>"; 
    the_link.innerHTML = "_('Some text')";
}

El último detalle es conseguir que Ruby-GetText extraiga las cadenas de nuestros ficheros .djs. Para ello, vamos a indicarle al parser de rhtml que “sabe” procesar nuestros ficheros djs. La tarea “Rake”: de actualización de los ficheros .po quedaría tal que así:

desc "Update pot/po files." 
task :updatepo do
  require 'gettext/utils'

  # 
  # ¡¡¡ Abracadabra!!!
  # 
  GetText::ErbParser.instance_variable_set(
      '@config', :extnames => ['.rhtml', '.r_js'])

  GetText.update_pofiles("app_domain",
   Dir.glob("{app,lib,bin}/**/*.{rb,rhtml,rjs,r_js}"), "App 1.0.0"")
end

Sencillo, ¿no?

Favicon en aplicaciones Rails en desarrollo

Publicado por el Miércoles, 02 de Mayo de 2007

Cuando generamos una aplicación Rails, en la carpeta public se crea el fichero favicon.ico. Si lo cambiamos por nuestro propio icono podremos verlo una vez hayamos desplegado la aplicación en nuestro servidor. Lo normal es que lo hagamos utilizando un Apache o un lighty y estos se encargarán de enviarle automáticamente el icono al navegador. En desarrollo utilizando un webrick o un mongrel esto no es así y no debemos olvidarnos de que si queremos ver el icono debemos enlazarlo expresamente en el header de nuestras páginas HTML con algo como:

<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />

Algo muy sencillo y que no nos cuesta nada escribir para poder ver como quedan nuestros favicons.

La propiedad table-layout en CSS

Publicado por el Sábado, 03 de Febrero de 2007

Como podéis ver en la especificación de CSS2, existe una propiedad CSS llamada table-layout que nos permite especificar al user agent (que para el 99% de nosotros es el navegador, para qué nos vamos a engañar) qué algoritmo debe utilizar a la hora de calcular el tamaño de una tabla para mostrarla. Los posibles valores para esta propiedad son fixed y auto.

table-layout: fixed

Cuando se especifica fixed el navegador deberá utilizar un algoritmo rápido, que calcula el ancho de la tabla basándose en el ancho de las celdas de la primera fila. De este modo, llega con que esta primera fila esté cargada: en ese momento el navegador ya puede determinar el layout de la tabla y pintar sus contenidos.

table-layout: auto

En este caso el navegador puede utilizar cualquier algoritmo, siendo lo más normal que emplee uno que determina el layout de la tabla en función del ancho de sus columnas (de toda la columna, no sólo de las celdas de la primera fila, como en el caso del algorito fixed). En este caso, hasta que no dispone de todo el contenido de la tabla, el navegador no puede determinar su layout definitivo.

Y saber esto… ¿de qué me vale?

Pues para un par de cosas, al menos. La primera y más evidente tiene que ver con la eficiencia. Si tenemos que mostrar grandes tablas de datos (grandes quiere decir grandes, muy grandes, con cientos o miles de filas; ya sé que existe la paginación, pero también sé que hay gente que prefiere no darse por enterada y quiere esas gigantescas tablas en sus aplicaciones), cambiar el algoritmo de auto (su valor por defecto) a fixed puede suponer la diferencia entre que el navegador se cuelgue o podamos ver la tabla.

La segunda ya no es tan evidente, pero en algunas ocasiones puede ser incluso más importante, y tiene que ver con la carga de los datos y su presentación al usuario. En nuestro caso concreto, acordarnos de la existencia de la propiedad table-layout resultó de gran utilidad mientras trabajábamos en la vista de Mendeleweb . Si visitáis la página podréis ver que lo primero que se muestra es una tabla periódica en la que cada celda contiene una foto de algún personaje (“elemento” en la jerga de Mendeleweb). Ahora mismo cada imagen se carga correctamente en su celda, posicionada en el lugar que le corresponde sobre la imagen de fondo, que representa los bordes de la tabla. Pero en las etapas iniciales del desarrollo las imágenes iban apareciendo a medida que se iban cargando y se iban colocando como un acordeón, hasta posicionarse correctamente en su lugar sólo cuando toda la tabla estaba cargada. Evidentemente, esto nos dio una pista muy buena e hizo que la propiedad table-layout viniese a nuestra memoria :o). Con sólo añadir esta propiedad y establecer su valor a fixed en las CSS conseguimos que los “elementos” de la tabla periódica apareciesen desde un primer momento en el lugar que Mendeleiev les asignó.

Nota mental: no olvidar el var

Publicado por el Domingo, 03 de Diciembre de 2006

A veces el domingo no es el típico día en que te tiras en el sofa a ver la vida pasar y recuperar fuerzas para ir el lunes a trabajar con un mínimo de alegría. A veces, el domingo, te dedicas a hacer labores de consultoría para los conocidos, amigos, familiares y demás. Hoy ha sido un domingo de esos. Y no uno llevadero, ha sido uno en el que te preguntas cada 20 segundos por qué leches te levantaste de la cama con lo bien que estabas roncando. En fin. Me estoy desviando del tema.

Nota mental: no olvidar el var.

Para ser breve, diré que mi labor de consultoría incluía la creación de un tag JSP que generaba un complicado formulario, que para más inri tenía que hacer filigranas JavaScript. La cosa iba como la seda, hasta que necesitamos recursión. Sí, recursión. No recuerdo haber necesitado hacer nada recursivo en JavaScript en mi vida, pero las circunstancias mandaban y no era el momento de buscar otras alternativas…

function hazAlgoConElNodo(nodo) {

   var nombreNodo = nodo.nodeName;
   var claseNodo = nodo.className;

   // etc, etc.   

    for ( i = 0; i < nodo.childNodes.length; i++)  {
       hazAlgoConElNodo(nodo.childNodes[i]);
    }
}

... código inocente donde los haya, con una recursión trivial. Pues nada, vamos a probarlo y ¡Upss! el navegador explota. ¡No me puedo creer que entremos en un bucle infinito!, ¡es imposible!, ¡mi%xc%$!, ¡c$j$s! y demás improperios. Nos calmamos, depuramos un poco, y … ¬_¬U … por qué leches me levanté de la cama con lo bien que estaba roncando.

 for ( var i = 0; i < nodo.childNodes.length; i++) {

Mucho mejor. Es lo que pasa cuando uno trabaja cuando debería estar descansando y no es capaz de leer lo que tiene delante. Hay que ver lo fácil que es olvidarse de un keyword importante en un lenguaje como JavaScript y no darse cuenta. Hay que tener mucho cuidado con el susodicho var que marca el ámbito de las variables (o scope, según el gusto lingüístico de cada cual).

A mi no me vuelve a pasar… espero xDDDD. Lo dicho, nota mental: no olvidar el var.