2012-12-10 10 views
89

Próba tworzenia obiektów i metod zadzwonić dynamicznie przezrubin wysłać metodę przejściu wielu parametrów

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

który działa dobrze, gdy

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

ale rzuca zły numer argumentów 1 do 2 dla

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

Zdefiniowana klasa losowa to

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 

Czy ktoś może mi pomóc w jaki sposób wysłać mutiple parametrów do metody ruby ​​dynamicznie

Odpowiedz

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

lub

send(:i_take_multiple_arguments, 25.0, 26.0) 
+17

Może warto zauważyć, że '*' w tym kontekście jest operatorem "splat". –

4

Można na przemian zadzwonić send z jego synonim __send__:

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

Przy okazji * możesz pa ss mieszań jako params oddzielonych przecinkami tak:

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

lub nowy hash składnia:

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

Według Black, __send__ bezpieczniej jest nazw.

„Wysyłanie to szerokie pojęcie: e-mail zostanie wysłana, dane zostaną wysłane do gniazd I/O, i tak dalej. Często zdarza się, że programy definiują metodę o nazwie send, która jest w konflikcie z wbudowaną metodą wysyłania Rubiego. Dlatego Ruby oferuje alternatywny sposób wywoływania: __send__. Zgodnie z konwencją nikt nigdy nie pisze metody o tej nazwie, więc wbudowana wersja Ruby jest zawsze dostępna i nigdy nie wchodzi w konflikt z nowo napisanymi metodami. Wygląda to dziwnie, ale jest bezpieczniejszy niż zwykły wysłać wersję z punktu widzenia metoda-name starcia”

Czarny sugeruje również zawijania wywołań __send__ w 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 

Ref: Black, David A. Dobrze ugruntowany Rubyist. Manning, 2009. P.171.

* Przyszedłem tutaj, szukając składni skrótu dla __send__, więc może być przydatne dla innych użytkowników Google. ;)