2012-12-10 17 views
89

Cercando di creare oggetti e chiamare metodi dinamicamenterubino invia metodo passa più parametri

Object.const_get(class_name).new.send(method_name,parameters_array) 

che funziona bene quando

Object.const_get(RandomClass).new.send(i_take_arguments,[10.0]) 

ma gettando numero errato di argomenti 1 per 2 per

Object.const_get(RandomClass).new.send(i_take_multiple_arguments,[25.0,26.0]) 

La classe casuale definita è

class RandomClass 
def i_am_method_one 
    puts "I am method 1" 
end 
def i_take_arguments(a) 
    puts "the argument passed is #{a}" 
end 
def i_take_multiple_arguments(b,c) 
    puts "the arguments passed are #{b} and #{c}" 
end 
    end 

Qualcuno può aiutarmi su come inviare mutiple parametri a un metodo rubino dinamicamente

risposta

169
send("i_take_multiple_arguments", *[25.0,26.0]) #Where star is the "splat" operator 

o

send(:i_take_multiple_arguments, 25.0, 26.0) 
+17

Vale la pena notare che il '*' in questo contesto è l'operatore "splat". –

4

È alternativamente possibile chiamare send con esso è sinonimo __send__:

r = RandomClass.new 
r.__send__(:i_take_multiple_arguments, 'a_param', 'b_param') 

A proposito * puoi pa ss hash come params separati da virgola in questo modo:

imaginary_object.__send__(:find, :city => "city100") 

o nuova hash sintassi:

imaginary_object.__send__(:find, city: "city100", loc: [-76, 39]) 

Secondo Black, __send__ è più sicuro di namespace.

"L'invio è un concetto generale: l'e-mail viene inviata, i dati vengono inviati alle prese I/O e così via. Non è raro che i programmi definiscano un metodo chiamato send che è in conflitto con il metodo di invio integrato di Ruby. Pertanto, Ruby ti offre un modo alternativo per chiamare send: __send__. Per convenzione, nessuno scrive mai un metodo con quel nome, quindi la versione integrata di Ruby è sempre disponibile e non entra mai in conflitto con i metodi scritti di recente. Sembra strano, ma è più sicuro rispetto alla pianura invia versione dal punto di vista del metodo-nome scontri”

nero suggerisce anche avvolgere le chiamate al __send__ in if respond_to?(method_name).

if r.respond_to?(method_name) 
    puts r.__send__(method_name) 
else 
    puts "#{r.to_s} doesn't respond to #{method_name}" 
end 

Rif .: Black, David A. Il Rubyist ben radicato. Manning, 2009. P.171.

* Sono venuto qui cercando la sintassi dell'hash per __send__, quindi potrebbe essere utile per altri googler. ;)