4Trabes Historias de una empresa en 100 metros cuadrados

El blog de Trabe Soluciones

Extensiones al core de Ruby, pequeños pedazos de código que harán tu vida más sencilla. Hoy Enumerable.pluck y Enumerable.invoke

| | Comentarios

En Trabe Soluciones vamos mejorando las librerías que utilizamos para desarrollar con Rails aplicación a aplicación. Puede decirse que somos como una esponja que va cogiendo buenas ideas de aquí y de allá. Hoy vamos a hablar de una par de extensiones al core de Ruby que utilizamos,

Primero el código:

1
2
3
4
5
6
7
8
module Enumerable
  def invoke(method_name)
    self.each { |o| o.send(method_name) }
  end
  def pluck(method_name)
    self.collect { |o| o.send(method_name) }
  end
end

Cómo podeís apreciar son unas sencillas funciones que solucionan dos tareas más que habituales cuando trabajamos con colecciones: invoke que invoca un método de cada elemento de un Enumerable y pluck que recolecta el resultado de invocar un método concreto sobre cada elemento de un Enumerable. Vamos, que abrevian dos construcciones típicas del lenguaje. Las hemos definido en el módulo Enumerable y no en la clase Array directamente para poder utilizarlas con cualquier clase que incluya este módulo (Array por ejemplo).

La inspiración de estas funciones se la debemos a Prototype, la famosa librería Javascript, que curiosamente se inspira a su vez en ruby:

Most of Prototype’s idioms are influenced by Ruby, and those that have no analog in Ruby defer to existing or emerging web standards

Para terminar un ejemplo autoexplicativo de su utilidad.

1
2
3
4
5
6
7
8
9
# ANTES
def find_by_object_keys(objects)
  find(:conditions => { :key => objects.collect { |o| o.key} }
end

# DESPUES
def find_by_object_keys(objects)
  find(:conditions => { :key => objects.pluck(:key) }
end

Ejercicio para lectores avispados: Ahora sólo tenéis que modificar las funciones para que acepten parámetros para el método invocado. Seguramente lo necesitéis en algún momento.

Lo sentimos, pero los comentarios están cerrados

Hola,

ActiveSupport añade a each y a collect/map una versión abreviada de la sintaxis (realmente lo que hace es definir Symbol#to_proc, si no me equivoco) que la deja muy parecida a lo que habéis creado, que dejaría el ejemplo así:

objects.collect(&:key)

Así que en aplicaciones Rails está disponible esta alternativa.

Saludos!

Tienes razón Sergio, existe esa posibilidad, aunque aquí en Trabe consideramos que es una construcción un poco oscura. Por otro lado la versión que utilizamos nosotros, permite hacer alguna cosa adicional fácilmente, por ejemplo, utilizar una cadena como parámetro en lugar de un símbolo (que puede considerarse algo menor) o más interesante, pasar parámetros a la función que se invoca (que como pone el post, queda como ejercicio para el lector ;)

Ejemplo práctico:

%w(un ejemplo).pluck(’*’,2) => [“unun”, “ejemploejemplo”]