Metodos definidos con simbolos

Veo que en RoR se usan mucho métodos que se invocan de esta forma

método :s1 => valor1, :s2 => valor2, etc.

por ejemplo

Usuario.find( :all, :conditions =>…)

o también

link_to :action=>…, :controller => …

¿Como se definen estos métodos?¿Es una característica reciente de Ruby?

un saludo

Rafa C. wrote:

Veo que en RoR se usan mucho métodos que se invocan de esta forma

método :s1 => valor1, :s2 => valor2, etc.

por ejemplo

Usuario.find( :all, :conditions =>…)

o también

link_to :action=>…, :controller => …

¿Como se definen estos métodos?¿Es una característica reciente de Ruby?

Que yo sepa, no. Esos métodos reciben un hash como parámetro. Ruby
permite en tal caso una notación abreviada:

Por ejemplo:

def metodo options
options.class
end

Así, las tres formas siguientes son equivalentes:

metodo({:action => ‘accion’, :controller => ‘controller’})
metodo(:action => ‘accion’, :controller => ‘controller’)
metodo :action => ‘accion’, :controller => ‘controller’

Y producen como resultado “Hash”.

On 9/30/07, Juan L. [email protected] wrote:

link_to :action=>…, :controller => …
options.class
end

Así, las tres formas siguientes son equivalentes:

metodo({:action => ‘accion’, :controller => ‘controller’})
metodo(:action => ‘accion’, :controller => ‘controller’)
metodo :action => ‘accion’, :controller => ‘controller’

Y producen como resultado “Hash”.

Además lo habitual es que ese parámetro donde se quieren englobar
varias opciones tenga como valor predeterminado {} (hash vacío). En
api.rubyonrails.org puedes ver un montón de ejemplos de esta técnica.
Por ejemplo
ActionView::Helpers::UrlHelper
(y pincha en “show source”).


Sergio Gil Pérez de la Manga
e-mail > [email protected]
blog > http://www.lacoctelera.com/porras

Claro, no se usan parentesis… lo que me despistaba era el uso de
símbolos.
Se supone entonces que todos esos simbolos los predefine Rails, ¿no?.
Pensaba yo que a lo mejor era una forma de asignar los valores
directamente
a los parametros que les correspondieran.

Gracias.

On Sep 30, 2007, at 3:06 PM, Rafa C. wrote:

Claro, no se usan parentesis… lo que me despistaba era el uso de
símbolos. Se supone entonces que todos esos simbolos los predefine
Rails, ¿no?. Pensaba yo que a lo mejor era una forma de asignar los
valores directamente a los parametros que les correspondieran.

En Ruby no es posible dar nombres a los argumentos que pasas a los
metodos:

str.gsub(re, s)

Para saber que argumento corresponde a que parametro se usa su
posicion. Esto es muy extendido, C, Java, Perl, … solo ofrecen
esa manera de pasar argumentos. Python por ejemplo, ademas del
convenio posicional, permite dar nombres a los parametros y hacer
referencia a ellos en llamadas por ese nombre, se llaman “keyword
arguments” en argot Python. Common Lisp y otros tambien lo ofrecen.

Cuando los argumentos son dos o tres la notacion posicional no es
mucho el problema, pero cuando aceptas 9 hacer una llamada asi:

obj.method(a1, a2, a3, a4, a5, a6, a7, a8, a9)

es fragil (es facil equivocarte de posicion), y poco legible, porque
no es obvio (en general) a simple vista que cosa es cada uno (puede
que en los argumentos vayan variables con buenos nombres, pero en
general no va muy bien). Imagina que a AR.find usara notacion
posicional en lugar de :conditions, :order, etc. seria algo bastante
parecido a un infierno :-).

Ruby no tiene keyword arguments, pero ofrece un truco para emular
esto que Rails explota por doquier: Si una llamada termina en una
cosa del tipo k1 => v1, k2 => v2, …, hara un apaño: lo recogera
todo en un hash que pasara como ultimo parametro al metodo. El metodo
entonces trata el hash, y el quid de la cuestion es que la API
documenta llaves de ese hash. No hay validacion en compilacion ni
nada por el estilo (las llaves son arbitrarias y el contrato no se
expresa en el codigo), pero es tremendamente util. Ademas, los
simbolos en Ruby se leen muy bien, por lo que suelen usarse como
llaves en esta tecnica.

Esto esta explicado en la seccion “Collecting Hash Arguments” del
Pickaxe (pag. 79-80).

– fxn

Gracias, monstruo…