2009-01-16 18 views
7

Próbuję dynamicznie definiować funkcje, które wywołują aż do innej funkcji, która przyjmuje parametr opcje:Czy można zdefiniować blok z opcjonalnymi argumentami w Ruby?

class MyClass 
    ["hour", "minute", "second"].each do |interval| 
    define_method "get_#{interval}" do |args| 
     some_helper(interval, args) 
    end 
    end 
    def some_helper(interval, options={}) 
    # Do something, with arguments 
    end 
end 

Chciałbym móc wywoływać różne metody na MojaKlasa w tych dwóch sposobów (zi bez argumentów opcjonalnych):

mc = MyClass.new 
mc.get_minute(:first_option => "foo", :second_option => "bar") 
mc.get_minute # This fails with: warning: multiple values for a block parameter (0 for 1) 

na drugim wywołaniu minutę, widzę to ostrzeżenie:

ostrzeżenie: wiele wartości dla parametru bloku (0 do 1)

  1. Czy istnieje sposób, aby napisać bloku na metodzie „get_ *” tak, że to ostrzeżenie nie będzie wymyślić?
  2. Czy używam metody define_method?

Odpowiedz

16

Jedyną zmianą, jakiej należy dokonać, jest zmiana args na *args. * wskazuje, że args będzie zawierał tablicę opcjonalnych argumentów do bloku.

+0

Dzięki za wskazanie tego! – Readonly

0

Zgadzam się z Gordonem dodając * do twoich argumentów sprawi, że odejdzie.

Innym sposobem na osiągnięcie tego jest użycie method_missing()

coś takiego:

class MyClass 

    def method_missing(m, *args) 
    if /get_(.+)/.match(m.to_s) 
     some_helper($1, args) 
    else 
     raise 'Method not found...' 
    end 
    end 

    def some_helper(interval, *args) 
    puts interval + ' -> ' + args.inspect 
    end 

end 

m = MyClass.new 
m.get_minute(:first_option => "foo", :second_option => "bar") 
+1

Wolałbym nazywać "super" w metodzie brakującej zamiast "podbić", więc wykona domyślną akcję Ruby, gdy naprawdę brakuje metody. – Priit

5

Dwa lata później ... ja nie wiem, czy jest to nowa funkcja z rubinem 1.9.2, lub jeśli to możliwe także w przeszłości, ale to działa:

class MyClass 
    ["hour", "minute", "second"].each do |interval| 
     define_method "get_#{interval}" do |args = {:first_option => "default foo", :second_option => "default bar"}| 
      some_helper(interval, args) 
     end 
    end 
    def some_helper(interval, options={}) 
     # Do something, with arguments 
     p options 
    end 
end 

mc = MyClass.new 
mc.get_minute(:first_option => "foo", :second_option => "bar") 
mc.get_minute 

Wynik jest:

{:first_option=>"foo", :second_option=>"bar"} 
{:first_option=>"default foo", :second_option=>"default bar"} 
+2

Tak, opcjonalne argumenty z wartościami domyślnymi są nowością w Rubim 1.9 –

Powiązane problemy