Trabe ya no escribe aquí. Puedes encontrarnos en nuestra publicación en Medium: medium.com/trabe.

4Trabes Historias de una empresa en 100 metros cuadrados

El blog de Trabe Soluciones

¡Feliz 2007!

| | Comentarios

Ya es 2007. Ha tenido que pasar todo un año para atragantarnos de nuevo con las uvas. Desde 4trabes.com, los miembros de Trabe Soluciones: Óscar, Marcos, Asís y David os desean un feliz año 2007.

Sitemaps autogenerados con Mephisto

| | Comentarios

Estos días hemos decidido que nos interesa que mephisto haga el solito sus deberes. El primer paso es que genere su sitemap, para sugerirle educadamente a Google que rutas quiere que sean indexadas. El segundo paso será entrenarlo para que notifique a los technorati y demás familia por si solo cuando haya cambios.

En teoría hacer lo primero es muy sencillo, porque hay un plugin que se supone que ya lo hace. Nada más fácil que esto…en teoria. Pero en la práctica esto no es del todo asi.

La buena noticia es que el plugin si que genera un sitemap, pero la mala es que simplemente con leerlo por encima nos damos cuenta de que este sitemap tiene algunos errores. Asi que vamos a arreglarlo para que sea algo más correcto. No buscamos una solución general, ni hacer un nuevo plugin, solo que funcione bien para nuestro caso.

El primer gran error, y el más garrafal en mi opinión, es que genera entradas en el sitemap para los articulos que aun no están publicados. Es decir, que todo lo que esté como draft va a aparecer igual en el sitemap, por supuesto con una ruta inválida. Localizar el código que hace esto es sencillo, está en el fichero index.rxml en la ruta /app/views/google_site_map/ del plugin. Echemos un vistazo a ver que puede estar pasando:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
xml.instruct! :xml, :version=> '1.0', :encoding => 'UTF-8'

xml.urlset( :xmlns => 'http://www.google.com/schemas/sitemap/0.84') do
  render :partial => "page", :locals => {
    :xm => xml,
    :loc => MephistoGoogleSiteMap.site_uri,
    :changefreq => MephistoGoogleSiteMap.home_frequency,
    :priority => MephistoGoogleSiteMap.home_priority,
    :lastmod => MephistoGoogleSiteMap.lastmod(@last_article)
  }
  for section in @sections do
    for article in section.articles do
      render :partial => "page", :locals => {
        :xm => xml,
        :loc => MephistoGoogleSiteMap.location(@site, article.to_liquid, section),
        :changefreq => MephistoGoogleSiteMap.change_frequency(section),
        :priority => MephistoGoogleSiteMap.article_priority,
        :lastmod => MephistoGoogleSiteMap.lastmod(article)
      }
    end
  end
end

El error parece evidente: para cada sección se iteran los artículos de la misma y para cada uno de ellos se pinta la entrada correspondiente en el sitemap. Buen intento, pero sería mejor hacerlo solo para aquellos artículos que estén publicados. Asi evitariamos meter los drafts en el sitemap. Solventar este pequeño problema es fácil. Con un if vamos sobrados:

1
2
3
4
5
6
7
8
9
10
11
12
13
for section in @sections do
  for article in section.articles do
    if article.published?
      render :partial => "page", :locals => {
        :xm => xml,
        :loc => MephistoGoogleSiteMap.location(@site, article.to_liquid, section),
        :changefreq => MephistoGoogleSiteMap.change_frequency(section),
        :priority => MephistoGoogleSiteMap.article_priority,
        :lastmod => MephistoGoogleSiteMap.lastmod(article)
      }
    end
  end
end

Podría escribirse de forma más elegante, pero dificilmente más sencillo. Bien, ya no nos salen los drafts, primer break point superado. Vamos a por el partido. El segundo problema que he detectado es que si un artículo está contenido en varias secciones – pongamos que está publicado en n secciones-, la entrada correspondiente del sitemap va a aparecer repetida n veces. Esto es de una utilidad discutible, asi que será mejor arreglarlo. Podriamos hacer una comprobación de si ya hemos generado una entrada o no…pero parece que esto se pone complejo, y no debería serlo, ¿no?…a lo mejor es que este bucle no está muy bien pensado, ¿por qué razón estamos iterando las secciones ?¿Para asignar la prioridad?¿Por qué existe la posibilidad de generar entradas de distinta prioridad para la misma url?…aqui veo lagunas no se…creo que se puede hacer muuucho más simple y además que funcione bien. Comentar que el tema de las secciones no-blog lo voy a eliminar, porque nosotros no lo usamos . Vamos a empezar por el controlador. No necesitamos iterar las secciones, con un listado de articulos ya nos llega, y además podemos poner la condición de que esté publicado directamente en el find, con lo que quitamos lógica de negocio de la vista, por aquello del estructurar. Asi, el método index de nuestro controlador google_site_map_controller.rb pasa de ser algo asi:

1
2
3
4
5
def index
  headers['Content-Type'] = 'text/xml; charset=utf-8'
  @sections = site.sections
  @last_article = Article.find_by_date(:limit => 1).first
end

a convertirse en algo como esto:

1
2
3
4
5
def index
  headers['Content-Type'] = 'text/xml; charset=utf-8'
  @articles = Article.find(:all,:conditions=>'published_at is not null')
  @last_article = Article.find_by_date(:limit => 1).first
end

Simplificamos un poco la clase del lib, eliminando algun método y simplificando algún otro:

1
2
3
4
5
6
7
8
9
  def get_frequency_for_article
  self.blog_frequency
end

def location(site, article)
  filters = FiltersProxy.instance
  article.instance_variable_set("@site", site)
  self.site_uri +  article.url
end

Como hemos comentado más arriba, hemos eliminado la particularidad de las secciones no-blog. Asi las cosas, el bucle de la vista que genera el sitemap, pasa a ser algo como esto:

1
2
3
4
5
6
7
8
9
for article in @articles do
  render :partial => "page", :locals => {
    :xm => xml,
    :loc => MephistoGoogleSiteMap.location(@site, article.to_liquid),
    :changefreq => MephistoGoogleSiteMap.get_frequency_for_article,
    :priority => MephistoGoogleSiteMap.article_priority,
    :lastmod => MephistoGoogleSiteMap.lastmod(article)
  }
end

Ya no tenemos los borradores en el sitemap ni entradas duplicadas, con lo que google estará más contento y más predispuesto a ser amiguito de nuestra página ;)

Pero aun no podemos cantar victoria: el formato en que se generan las fechas no es acorde a lo definido por el W3C. Esto es fácil de subsanar: en el init.rb del plugin se encuentra definido el simbolo :w3. Solo hay que tocar esa definición para añadirle información sobre vuestra zona horaria:

1
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.update(:w3 => '%Y-%m-%dT%H:%M:%S+01:00')

Y ahora si que es posible que tengamos un sitemap decentillo.

David Heinemeier deja 37signals

| | Comentarios

David Hennemeier Hanson, creador de la plataforma Ruby On Rails, anuncia que dejará 37signals la empresa en la que ha trabajado durante los últimos años para pasar a formar parte de la plantilla de Sun Microsystems. (Yeah man, you read it right! Google translator is not kidding you, DHH joins Sun!).

David ha tomado la decisión tras haber disfrutado de una suculenta comida de Navidad en casa de su buen amigo James Gosling, creador de Java, con el que trabajará en estrecha colaboración. Se sabe que el menú estuvo formado por arenques en vinagre y pavo asado preparados de forma excelsa por la esposa de Gosling. David y James se conocieron en la Java One Conference 2006 a la que DHH acudió de incógnito, desde entonces ha existido entre los dos una gran amistad que culmina con esta noticia.

En su nueva etapa en Sun, DHH pasará a formar parte del equipo que desarrolla la nueva versión de Java 7.0 (Dolphin) a la que aportará su experiencia en el trabajo con Ruby. Por otra parte colaborará en la publicación de los nuevos Java blueprints que en su opinión son una “referencia indespensable en el mundo de la programación, tanto en Java como en cualquier lenguaje”.

Afortunadamente disponemos del video del momento en el que DHH hace pública esta sorprendente decisión. David asegura que siempre ha querido trabajar al lado de gente tan importante como su gran amigo Gosling y que tras años buscando la belleza sin encontrarla necesita reorientar su vida y darle un poco de orden. Aquí podeis ver sus declaraciones.

Por su parte el CEO de 37signals Jason Fried afirma que respeta la decisión de David y que lo apoyará en el futuro. En distintos foros y blogs technogeeks se apunta que en los últimos meses la relación de Fried y Heinnemeier se había deteriorado. El motivo de las tensiones podría ser la aficción por los arenques en vinagre que DHH comparte con James Gosling.

Ciertamente se trata de una noticia conmocionate, si hoy no fuera 28 de Diciembre diría que se trata de una broma ;-)