Logo de La Coctelera

Categoría: Desarrollo Web

Ruby on Rails Desarrollo Web Snippets y Trucos

Generating static maps with attachment_fu and static-gmaps gem

Google Maps is, may be, the coolest service for integrating maps in your web applications: it offers a powerful and easy API with no limit usage.

The problem is that it loads quite Javascript that has to connect to the main Google Maps page in order to draw our map. In order to avoid that we can use static Google Maps, it is, a picture (generated in real time) of the map we want to visualize. The problem with this is that you can't interact with the map (because it is an image) and that there is a limitation per day. But may be you find it useful in a particular moment.

For example, in iwannagothere.net we have a small map in every place that shows the location of that city:

In that situation we can change the map because the map is not for navigating along the city. For that you have a map in each item.

In Ruby on Rails, the programming framework of iwannagothere.net there is a gem called static-gmaps that does the hard work for you. What's more, we have found the way to integrate this maps with attachment_fu, in order you save a copy of the map in your filesystem and then avoid the day limitation usage.

Basically we have an attachment_fu kind of model (nothing special here):

class PlaceMap < ActiveRecord::Base
   belongs_to :place
 
   has_attachment  :content_type => :image, 
                   :storage => :file_system,
                   :processor=> :rmagick,
                   :path_prefix => 'public/userfiles/place_maps', 
                   :max_size => 1.megabyte
 
   validates_as_attachment  
 end
 

The we generate the static map instance:

	
 map = StaticGmaps::Map.new :center   => [ place.lat, place.long ],
                             :zoom     => 12,
                             :size     => [ 334, 144 ],
                             :key      => APP['gmkey']  
 

And save it in our PlaceMap model:

 PlaceMap.create(:uploaded_data => (open(map.url)), :place_id => place.id, :content_type => 'image/gif')
 

The problem here is that we are not uploading a file in the usual way: we are trying to save a raw of data. Attachment_fu doesn't know how to do that, so we have to apply a little patch:

 module Technoweenie
   module AttachmentFu
     module InstanceMethods
 
       def uploaded_data=(file_data)
         return nil if file_data.nil? || file_data.size == 0
         self.content_type = file_data.content_type
         self.filename     = Time.now.to_i.to_s+'.gif'
         if file_data.is_a?(StringIO)
           file_data.rewind
           self.temp_data = file_data.read
         else
           self.temp_path = file_data
         end
       end          
 
     end
   end
 end
 

Here we are giving a random filename, generated from the current time.

And that's all, really easy :)

compártelo favorito Tags: , , ,

Ruby on Rails Desarrollo Web

Sobre httperf y las pruebas de carga

Andaba yo viendo esta mañana el screencast de Peepcode Benchmarking with httperf bastante emocionado (ya que la fama precede a estos screencasts) para ver cómo podía mejorar las pruebas de rendimiento que estoy haciendo contra una aplicación Rails que he instalado en mi recién adquirido Slicehost.

La situación es la siguiente: es una cuenta Slicehost de 256Mb de memoria, en el que tú instalas lo que quieres. El problema es que debes de instalar un servidor web, los servidores de aplicaciones y la base de datos, y todos ellos han de luchar por esos 256Mb. Así que al final me he decidido por instalar esto:

  • servidor web: Nginx, que tenía ganas de probarlo tras leer a uno de los sysadmins decir que Nginx era lo más estable que había visto nunca, y que recomendaba usar Apache sólo en el caso de querer que un mismo servidor web compartiera diferentes aplicaciones y en distintos lenguajes (PHP y Rails, por ejemplo). Además, su uso de memoria es ridículo.
  • servidor de aplicaciones: Mongrel. Considerando los 60Mb que viene a consumir un Mongrel de memoria, el número de Mongrels en el clúster lo he establecido a 3.
  • servidor de base de datos: MySQL. No había otra opción.

Además de todo esto, hay un servidor Memcached de 32Mb para guardar las sesiones.

Y claro, quería hacer pruebas de carga contra el stack completo para ver de rendimiento qué tal.

Las pruebas se han realizado contra una página sin caché y con bastantes consultas a la base de datos, cuyo tiempo de respuesta medio es de 0.005 segundos o lo que es lo mismo, unas 20 req/s.

El screencast

El screencast se queda algo corto en cuanto a uso de la herramienta httperf, ya que el autor pierde mucho tiempo explicando conceptos teóricos y muy básicos de Estadística: media y desviación estándar, así como cómo mostrar luego los resultados a través de gráficas (unas muy bonitas generadas con gruff).

Posteriormente las pruebas las realiza contra un único Mongrel, explicando con todo detalle:

  • la importancia de utilizar datos reales: la muestra debe de ser representativa para que los resultados lo sean
  • la importancia de obtener muchas muestras: cuantas más muestras, la media y la varianza son más significativas también
  • la importancia de anotar todos los resultados
  • la importancia de la interpretación de los mismos en función de los resultados obtenidos y entender qué significan

Las pruebas las realiza para comparar el rendimiento de su aplicación sin usar caché, utilizando caché de acción y utilizando caché de página. Así que establece el baseline en los resultados obtenidos sin utilizar caché y a partir de los obtenidos utilizando caché establece porcentajes de mejora.

Otros aspectos a tener en cuenta

Hay otras muchas situaciones en las que es recomendable hacer pruebas de rendimiento contra tu propia aplicación:

  • calcular el número de Mongrels a lanzar en el servidor de aplicaciones. Una buena explicación (aunque breve también), la da Zed en la página de Mongrel: How many Mongrels
  • comparar el rendimiento entre distintos sistemas de almacenamiento de sesiones
  • comparar distintos algoritmos de balanceo en el módulo de proxy
  • determinar el tope máximo de ficheros servidos a través de una unidad NFS
  • ...

En estos casos es posible que nos interese conocer algún parámetro más de httperf que los que se han explicado en el vídeo:

  • --rate: determinar el número de peticiones concurrentes lanzadas en un segundo
  • --wsess: determina cada cuántas peticiones se inicia una nueva sesión

Y además, si vais a hacer pruebas de carga, hay que tener en cuenta estas perogrulladas, que a veces no lo son tanto:

  1. el número de Mongrels en el clúster
  2. la conexión: ¡no hagas las pruebas con un ADSL! En mi caso he pasado de 30 req/s a más de 50 req/s sólo por lanzar las pruebas desde una máquina con una conexión decente
  3. testea el stack entero: sobre todo porque es interesante ver si hay problemas de conectividad entre una capa (web) y la otra (aplicación), o si el proxy que reparte la carga está mal configurado, etcétera
compártelo favorito Tags: , , ,

Ruby on Rails Desarrollo Web The Cocktail

La polémica de la escalabilidad de Twitter

El equipo de desarrolladores de The Cocktail hemos escrito una pequeña documentación sobre cómo hemos resulto nosotros el problema de la lectura de varias bases de datos simultáneamente utilizando Ruby on Rails.

Todo, dicho sea de paso, a raíz de la polémica generada por la entrevista a Alex Payne (un desarrollador de Twitter), la contestación de David HH y los comentarios chismosos de algún blogger amarillo de esta nuestra blogosfera, cuyo blog no citaré.

Por cierto, lo podéis leer directamente desde aquí (pdf).

Y si queréis bucear un poquito más, en la lista de correo de Ruby on Rails en castellano se está generando un hilo muy bonito, con gran cantidad de información, y sin trolls ni polémicas.

compártelo favorito Tags: , ,

Web 2.0 Desarrollo Web Charlas y Presentaciones

serestandar.es

Acaba de anunciarse serestandar.es una iniciativa que pretende ser

Un conjunto de talleres y conferencias sobre diseño y desarrollo web con estándares, en los que participarán como ponentes muchos de los mejores diseñadores y desarrolladores cuyo método de trabajo está basado en el respeto a los estándares web.

Allí estaremos algunos conocidos del sector durante tres días, hablando sobre web y estándares, así que parece que será interesante y divertido.

El evento tendrá lugar del 27 al 29 de junio en Sevilla.

compártelo favorito Tags: , , , ,

Javascript In web we trust Desarrollo Web

Colorea código Ruby, Javascript, HTML y CSS de forma no intrusiva

La falta de coloreado de código es, desde que tengo este blog, una de las cosas que más echaba de menos en The-Shaker.

Sin embargo, gracias a Dan Webb, del que soy fan desde la Conferencia Rails de Londres, y a su CodeHighlighter el problema está más o menos resuelto:

por un lado se deben de incluír los ficheros javascript necesarios: uno básico y el resto según los lenguajes que queramos colorear.


 <script type="text/javascript" src="code_highlighter.js"></script>
 <script type="text/javascript" src="javascript.js"></script>
 <script type="text/javascript" src="css.js"></script>
 <script type="text/javascript" src="html.js"></script>
 <script type="text/javascript" src="ruby.js"></script>
 

Posteriormente, a cada bloque de código que queramos colorear le debemos de dar como nombre de clase, el lenguaje en cuestión. Por ejemplo:


 <pre><code class="ruby">
   def foo
     puts "bar"
   end
 </code></pre>
 

Y, por último, debemos de dotar de estilos al HTML al código que queramos colorear. Por ejemplo, mi hoja de estilos es tal que así, aunque la pienso ir ampliando:


 pre {
   border: 1px solid black;
   border-color: #BBB #DDD #DDD #BBB;
   padding: 0.2em 1em;
   line-height: 1.2;
   background: white;
 }
 code {
   font-size: 1.2em;
 }
 .javascript .comment, .ruby .comment {
   color : green;
   font-weight: bold;
 }
 .javascript .string, .ruby .string {
   color : teal;
 }
 .javascript .keywords, .ruby .keywords {
   color : navy;
 }
 .javascript .global {
   color : blue;
 }
 .javascript .brackets, .ruby .brackets {
   color : navy;
 }

De momento colores muy sosos, pero cogiendo los de Textmate, por ejemplo, puede quedar algo más "bonito".

compártelo favorito Tags: , ,

Desarrollo Web Snippets y Trucos

mod_redirect y mod_rewrite en lighttpd

Lighttpd, tu servidor web favorito, es muy poco peculiar a la hora de tratar redirecciones y reescrituras a la vez, debido a que realiza la reescritura antes que la redirección, con lo cuál la redirección se realiza con la URL ya reescrita.

Para evitarlo, basta con seguir estos pasos los pasos que encontré en este post.

En primer lugar el orden de los módulos importa, y debes de cargar el módulo mod_redirect antes que el mod_rewrite, tal que así:

 server.modules  = ( "mod_rewrite", "mod_fastcgi", "mod_accesslog", "mod_redirect" )
 

En segundo lugar debes de indicar, en primer lugar la redirección que quieras, por ejemplo:

 url.redirect = (
   "^/(.*)" => "http://www.site.com/$1"
 )
 

Una regla de redirección típica, que añade las www a cualquier URL que no las tenga.

A continuación debemos añadir las reglas de reescritura que queramos, añadiendo una regla especial al principio:

 url.rewrite-once = (
   "^/([-_a-zA-Z0-9]+)/image?n?/(.+)$" => "/myfiles/$1/$2",
   "^/(.*)" => "$0"
 )
 

La regla, lo que hace es reescribirse a sí misma, para evitar que la redirección se realice con la URL ya reescrita.

Y esto no funcionaría sin el rewrite-once , para no entrar en una reescritura infinita.

Y ahora me pregunto, ¿por qué nadie ha escrito sobre esto en la documentación oficial?

Actualización:

he actualizado la sección del rewrite, de ésta:

 url.rewrite-once = (
   "^/(.*)" => "$0",
   "^/([-_a-zA-Z0-9]+)/image?n?/(.+)$" => "/myfiles/$1/$2"
 )
 

a ésta:

 url.rewrite-once = (
   "^/([-_a-zA-Z0-9]+)/image?n?/(.+)$" => "/myfiles/$1/$2",
   "^/(.*)" => "$0"
 )
 

Y es que la regla hack para las redirecciones se aplica siempre, y debe aplicarse al final, después del resto de reglas, para que éstas funcionen.

compártelo favorito Tags:

Ruby on Rails Desarrollo Web La Coctelera

10 consejos para optimizar Rails

Antonio Cangiano publica 10 tips sobre rendimiento de Rails bastante interesantes. No están todos los que son, ni son todos los que están, pero como comienzo está muy bien.

De hecho, pienso que es tan necesario conocer y saber programar Rails de forma correcta, es decir, aprovechando todas las bondades de ActiveRecord, el patrón MVC, etcétera, como saber escribir código eficiente. Y lo bueno es que en Rails lo uno no está reñido con lo otro.

Para mí ha resultado crucial leer la presentación de Stefan Kaes titulada Performance Rails, ha sido como un antes y un después para empezar a tener en mente eso de que el rendimiento importa (eso y el hecho de haber tenido que lanzar la nueva coctelera, cargada de nuevas features, algunas bastante críticas a nivel de rendimiento).

Si leéis la presentación, tened en cuenta que el autor es un poco radical, y que no hay que tomarse al pie de la letra todo lo que dice, más que nada, porque muchos de sus consejos implican dejar de utilizar "la magia de Rails" (la magia tiene un coste computacional, sí) por cosas más rudimentarias.

Mi consejo es que ni tanto ni tan poco, que se puede llegar a un equilibrio bastante fácilmente y para el que los resultados salten a simple vista.

compártelo favorito Tags: , ,

Aplicaciones Web In web we trust Web 2.0 Desarrollo Web

En Planet Webdev

Hace ya unos meses inauguró un planeta sobre desarrollo web llamado Planet Webdev, que agrega contenido de interés sobre desarrollo web: WordPress, PHP, HTML + CSS, Javascript son los temas mayoritarios, aunque podéis encontrar también configuración de servidores web, hacks o consejos varios.

Hoy por fin, me he decidido a solicitar admisión a raíz de este post, así que a partir de ahora me podéis leer ahí también.

Y si tu blog trata sobre desarrollo web, ¿por qué no te apuntas?

compártelo favorito Tags: , , , ,