Truco: Cómo obtener una clase o objeto a partir de un string con su nombre en ruby on rails

Ese es un post corto. Creo que sería buena idea hacer una sección de pequeños trucos medianamente regular.

Yo soy bastante fanático de haces parciales. A veces creo que me paso de rosca incluso en tratar de hacer vistas tan genéricas que sirvan para satisfacer todos los modelos. El truco de hoy alimenta esa enfermedad.

Muchas veces al generalizar, necesitamos obtener un objeto de una determinada clase, y esa clase no la sabemos de antemano, pero sabemos que vamos a poder tener su nombre (nos viene por parámetro, depende del nombre de la acción, ect). En esos casos nos encontramos siempre con un String.

La tendencia natural de la gente que ha programado en Camel, es probar la omnipresente sentencia eval. Suponiendo que queremos obtener el numero de patas de un perro (asumiendo que es un método de clase y no existen los perros cojos en el mundo feliz), haríamos algo así:

    className = "Dog"
    eval className + '.legs' #=> 4

Esto equivale exactamente a invocar en la consola IRB el comando Dog.legs. Funciona, pero no es elegante, y eval es una función que hay que usar con precaución. Podeis tener más información sobre esto leyendo artículos como Eval is Evil: Part One o Eval is Evil: Part Two. Tratan de la función eval en javascript pero lo que dicen es extrapolable a casi todos los lenguages de script.

En lugar de evaluar un expresión, deberíamos obtener la verdadera clase. Lo bueno es que en Ruby las clases son constantes, y hay una función del kernel que nos devuelve contantes por su nombre.
Así podríamos hacer lo mismo de la siguiente manera

    className = "Dog"
    Kernel.const_get(className).legs #=> 4

Es una solución más elegante.
Además, RoR facilita este proceso con un método la mas de útil que transforma un string en el nombre de una clase siguiendo las convenciones de nomenclatura de rails. Elimina los plurales y transforma las palabras separadas por subrayados en CamelCase. Es el método classify

    "dog".classify #=> "Dog"
    "animals".classify #=>"Animal"
    "farm_animals".classify #=>"FarmAnimal"

Combinando este método y Kernel.const_get(className) podeis obtener clases o instanciar objetos a partir de su nombre facilmente.

Anuncios

, , ,

  1. #1 por Lorene Macbean el enero 26, 2011 - 5:16 am

    Donde esta el rss de su blog?

    • #2 por miguelcamba el enero 26, 2011 - 9:25 am

      He añadido un widget para suscribirse por RSS al blog. Hasta ahora solo daba opción a hacerlo via Twitter. Comprueba que funcione correctamente

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: