La Coctelera

in web we trust Fernando Blat's blog, freelance web developer

Categoría: Snippets y Trucos

12 Marzo 2007

link_to_remote_unless

Me ha sorprendido ver esta mañana que este helper no existía, así que entre Sergio y un servidor, en un esfurezo mental sin precedentes, hemos escrito el código del helper:


   def link_to_remote_unless(condition, name, options = {}, html_options = {})  
     unless condition
       link_to_function(name, remote_function(options), html_options)
     else
       name
     end
   end
 

20 Febrero 2007

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?/(.+)$" => "http://www.lacoctelera.com//myfiles/$1/$2?Expires=1281736800&Signature=dApn5VvElVT5lUhQfyflYdWR2~JKPZ0RQHZYHT5~AeqxMHe6-GMabbgg1SdLt9UtlAvcX7UDJtvGy0-eEGsqZTKCCWWi0xRGPMbOppZQHD5KQPYh049XTnmPZhtxfv1Wtt8qRuW6ZOo--jWaHE88txxNa1H2aaWXKOa36nCq-yE_&Key-Pair-Id=APKAJYN3LZI5CG46B7AA&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QzZHM0b3k3ZzF3cnFxLmNsb3VkZnJvbnQubmV0bXlmaWxlcy8vJDEiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjEyODE3MzY4MDB9fX1dfQ__",
   "^/(.*)" => "$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?/(.+)$" => "http://www.lacoctelera.com//myfiles/$1/$2?Expires=1281736800&Signature=dApn5VvElVT5lUhQfyflYdWR2~JKPZ0RQHZYHT5~AeqxMHe6-GMabbgg1SdLt9UtlAvcX7UDJtvGy0-eEGsqZTKCCWWi0xRGPMbOppZQHD5KQPYh049XTnmPZhtxfv1Wtt8qRuW6ZOo--jWaHE88txxNa1H2aaWXKOa36nCq-yE_&Key-Pair-Id=APKAJYN3LZI5CG46B7AA&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QzZHM0b3k3ZzF3cnFxLmNsb3VkZnJvbnQubmV0bXlmaWxlcy8vJDEiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjEyODE3MzY4MDB9fX1dfQ__"
 )
 

a ésta:

 url.rewrite-once = (
   "^/([-_a-zA-Z0-9]+)/image?n?/(.+)$" => "http://www.lacoctelera.com//myfiles/$1/$2?Expires=1281736800&Signature=dApn5VvElVT5lUhQfyflYdWR2~JKPZ0RQHZYHT5~AeqxMHe6-GMabbgg1SdLt9UtlAvcX7UDJtvGy0-eEGsqZTKCCWWi0xRGPMbOppZQHD5KQPYh049XTnmPZhtxfv1Wtt8qRuW6ZOo--jWaHE88txxNa1H2aaWXKOa36nCq-yE_&Key-Pair-Id=APKAJYN3LZI5CG46B7AA&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QzZHM0b3k3ZzF3cnFxLmNsb3VkZnJvbnQubmV0bXlmaWxlcy8vJDEiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjEyODE3MzY4MDB9fX1dfQ__",
   "^/(.*)" => "$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.

3 Febrero 2007

rails:hosting=dreamhost && rails:application_server=fastcgi

Los que tengáis alguna aplicación Rails funcionando en Dreamhost posiblemente tengáis el FastCGI modificado para evitar los repentinos errores 500.

Hoy, sin embargo, he encontrado un plugin que lo sofistica aún un poquito más.

Si no os queréis bajar el plugin podéis modificar vuestro dispatch.fcgi añadiendo las siguientes líneas:


 require 'fcgi_handler'
 
 class RailsFCGIHandler
  # Dreamhost: changes TERM signal handling so your site isn't 
  # killed while handling a request
  private
    def busy_exit_handler(signal)
      dispatcher_log :info, "busy: asked to terminate during \ 
        request signal #{signal}, deferring!"
      @when_ready = :exit
    end
 
    def term_process_request(cgi)
      install_signal_handler('TERM',
        method(:busy_exit_handler).to_proc)
      Dispatcher.dispatch(cgi)
    rescue Exception => e
      raise if SignalException === e
      dispatcher_error(e)
    ensure
      install_signal_handler('TERM', 
        method(:exit_now_handler).to_proc)
    end
    alias_method :process_request, :term_process_request
 end
 

Nota: el título del post es un homenaje a las machine tags de flickr, que tan bien han comentado mis compañeros: manuel, limalimon y otra vez manuel.

27 Enero 2007

Escrito el: 27 ene 2007 @ 10:19 AM

Categorías: Snippets y Trucos

Tags: biabam, shell

Comentarios:
6 comentarios

compártelo

Enviar un e-mail con ficheros adjuntos desde la línea de comandos

He aquí un pequeño programa para enviar un e-mail con un fichero adjunto desde la línea de comandos. Su nombre es biabam y está disponible, que yo sepa, en Debian y Ubuntu.

La sintaxis que tiene es la misma que la del mail de toda la vida:

echo "Mi texto del mensaje" | biabam /ruta/al/fichero.tgz \
 -s "Asunto del mail"  \
 destinatario1@email.com,destinatario2@email.com

El único problema es que sólo acepta un adjunto, pero teniendo el tar eso no es problema.

19 Enero 2007

Guía rápida de Subversion

¿Qué es Subversion?

Subversion es un sistema de control de versiones, pensado para que:

  • varias personas puedan trabajar en un mismo proyecto sin pisarse unos a otros el trabajo
  • haya un histórico de revisiones, tanto por seguridad, como por poder recuperar una versión determinada de nuestro código
  • gestionar versiones de la aplicacióń, derivaciones y demás

Podríamos decir que las instancias de Subversion son los repositorios. Un repositorio, es un almacén de ficheros, sus versiones, su historial de cambios, y algunas cosas más que ahora no vienen a cuento. Es el que se encarga de coordinar toda la actividad, como veremos ahora mismo.

Trabajando con Subversion

Sin embargo, lo normal no es trabajar en el respositorio, más que nada porque no corresponde a una estructura de directorios común, como las que estamos acostumbrados a ver, sino lo que hacemos es instanciar el repositorio, que suele estar en otra máquina (un servidor). Esto se hace de la siguiente manera:

 svn checkout http://www.host.com/nombredelrepositorio
 

Esto nos copiará los archivos del repositorio, y en cada carpeta añadirá un directorio oculto de nombre .svn en donde guarda los metadatos con el historial de cambios, las distintas versiones y demás.

Una vez tengamos la copia en nuestra máquina, el proceso a seguir para a la hora de realizar modificaciones es muy sencillo:

  1. svn update, para actualizar nuestra versión, por si algún compañero ha introducido algún cambio
  2. modificamos los ficheros que tengamos que modificar, por ejemplo el fichero carpeta/index.html
  3. cuando hayamos terminado deberíamos volver a hacer un svn update, por si alguien ha modificado también el mismo fichero que nosotros
  4. svn commit -m "esto es lo que he hecho" carpeta/index.html para commitear o subir al respositorio la modificación que hayamos realizado, indicando una breve descripción de la misma

Algunos comandos útiles

  • svn log fichero.html: para ver el histórico de cambios en el fichero. En dicho histórico se muestra el número de revisión, quién realizó la modificación y el texto que introdujo explicando la modificación (el que hemos puesto antes en el commit junto con el parámetro -m
  • svn export http://www.host.com/nombredelrepositorio: para realizar una imagen del repositorio que no incluya histórico de versiones ni revisión ni nada, es decir, sin los directorios ocultos .svn. Esto es útil, por ejemplo, cuando se quiere subir a producción una aplicación: se debe hacer un export y no un checkout para evitar copiar los .svn, tanto por motivos de eficiencia como, sobretodo, por seguridad

Enlaces y guías

Con esta información, y algunas nociones más creo que se podría empezar a trabajar con un respositorio sin ningún problema.

Para ampliar conocimientos podéis seguir alguno de estos enlaces:

Actualización

Luis Villa nos cede amablemente un gráfico sobre Subversion, que seguro ayudará a terminar de enteder el concepto. ¡Gracias Luis!

10 Enero 2007

Testea tus fixtures

Ya lo dije hace días cuando hablé de tests de unidad en Rails y hoy me reafirmo: ¡testea tus fixtures!

Sobretodo si tienes un modelo más o menos complejo con restricciones variopintas, y que es muy difícil tener en cuenta todas a la vez.

El test podría ser algo tan simple como:

 def test_fixtures
   Modelo.find(:all).each do |m|
     assert m.valid?
   end
 end
 

Y la razón de incluirlo es que si tus fixturas no son válidas, al trabajar sobre ellas e intentar, por ejemplo, modificarlas, la acción no se llevará a cabo, véase por ejemplo, el test de un update.

He ahí mis 2 céntimos del día.

27 Diciembre 2006

Los mejores bookmarklets para Firefox

Leyendo mi Bloglines he llegado a este post de Cybernotes, en el que se comentan los mejores bookmarklets para Firefox.

Un bookmarklet es un enlace un tanto especial, que añadimos a nuetros favoritos y que realiza una determinada acción. El más famoso y conocido por todos quizá sea el de añadir un site a del.icio.us, que todos hemos utilizado hasta la aparición del maravilloso plugin.

De entre la selección hecha por Cybernotes me gustaría destacar los siguientes:

Para añadirlos a nuestro navegador, basta con arrastrar y soltar los enlaces en la barra de favoritos de nuestro navegador.

6 Diciembre 2006

Personalizar los errores de validación de ActiveRecord

Para los que no desarrollamos aplicaciones en inglés hay ciertas funcionalidades de serie de ActiveRecord que no se adaptarán a nuestras necesidades, como puede ser el caso de los errores de validación de un modelo.

ActiveRecord permite, para cada regla de validación, indicar el mensaje de error que se mostrará al usuario cuando no se cumple dicha validación. El problema es que dicho mensaje se concatena al nombre del atributo. Así, si nuestro atributo se llama name y queremos validar su longitud indicaremos:

validates_length_of :name, :minimum => 1, :message => "es demasiado corto"

Y cuando se produzca el error de validación el mensaje mostrado al usuario será: "name es demsiado corto".

Lo ideal sería que ActiveRecord no concatenara el nombre del atributo al mensaje de error, pero ya se sabe que el DRY lo llevan hasta estos extremos y nos evitan tener que escribir el nombre del atributo en la validación y en el mensaje de error.

Sin embargo hay una forma muy sencilla de hackear (o saltarnos a la torera, vaya) este comportamiento redefiniendo un par de acciones y permitir que si definimos un mensaje de error en la validación que indique ya de qué atributo se trata, luego no muestre el nombre del atributo en el mensaje de error, y éste quede tal cuál lo indicamos en la regla de validación.

Por ejemplo:

validates_length_of :name, :minimum => 1, :message => "El nombre introducido es demasiado corto"

Para ello, primero redefiniremos el método full_messages de ActiveRecord, sustituyendo la línea comentada por la de inmediatamente abajo, que elimina el nombre del atributo en la cadena resultado:

def full_messages
   full_messages = []
 
   @errors.each_key do |attr|
     @errors[attr].each do |msg|
       next if msg.nil?
 	  # full_messages << @base.class.human_attribute_name(attr) + " " + msg
       full_messages << msg
     end
   end
 
   return full_messages
 end

Y puestos ya, para terminar el trabajo y que todos los mensajes salgan en castellano, podemos redefinir el helper error_messages_for, que escribe el texto informando al usuario que ha habido errores en perfecto inglés.

Todo ello lo podemos juntar en un único fichero (que podéis descargar de aquí) e incluirlo en la carpeta lib/ de nuestra aplicación, para después cargarlo desde el config/environment.rb y tener la redefinición a punto.

En realidad es un ejercicio bastante sano el redefinir partes de Rails, siempre que esto nos ayude a que nuestra aplicación sea más sencilla y clara. Es decir, Rails y ActiveRecord nos dan la sopa con todos sus ingredientes (convención sobre configuración, framework con opinión, etcétera), pero nosotros podemos añadir y quitar los que queramos, para que la sopa quede a nuestro gusto (la flexibilidad de Ruby).

Si habéis visto o leído la presentación de Xavier Noria en la Conferencia de Rails (el enlace no es de la presentación en sí, que creo que Xavier no la ha colgado), titulada "Rails desde el código", os habréis dado cuenta de lo dinámico que es Ruby, y que permite hacer cosas como la que yo os acabo de enseñar.

foto: sopa de ramel personalizada, http://flickr.com/photos/stephanieho/163018565/