Szukaj…


Parametry

Parametr Detale
metoda Nazwa metody, która została wywołana (w powyższym przykładzie jest to :say_moo , zauważ, że jest to symbol.
* argumenty Argumenty przekazane do tej metody. Może być dowolną liczbą lub żadną
&blok Blok z metodą zwaną, może być albo do bloku lub { } zamknięty blok

Uwagi

Zawsze wywołuj super, na dole tej funkcji. To oszczędza cichą awarię, gdy coś zostanie wywołane i nie pojawi się błąd.

Na przykład ten brak metody spowoduje problemy:

class Animal
  def method_missing(method, *args, &block)
    say, speak = method.to_s.split("_")
    if say == "say"
      speak
    end
  end
end

=> Animal.new.foobar
=> nil # This should really be raising an error

method_missing jest dobrym narzędziem do użycia, gdy jest to właściwe, ale ma dwa koszty, które należy wziąć pod uwagę. Po pierwsze, method_missing jest mniej wydajna - ruby musi przeszukać klasę i wszystkich jej przodków, zanim będzie mógł powrócić do tego podejścia; ta kara za wydajność może być trywialna w prostym przypadku, ale może się sumować. Po drugie i szerzej, jest to forma metaprogramowania, która ma wielką moc, która wiąże się z odpowiedzialnością za zapewnienie, że wdrożenie jest bezpieczne, odpowiednio obsługuje złośliwe dane wejściowe, nieoczekiwane dane wejściowe i tak dalej.

Powinieneś również przesłonić odpowiedź na respond_to_missing? tak jak:

class Animal
  def respond_to_missing?(method, include_private = false)
    method.to_s.start_with?("say_") || super
  end
end

=> Animal.new.respond_to?(:say_moo) # => true

Łapanie wywołań niezdefiniowanej metody

class Animal
  def method_missing(method, *args, &block)
    "Cannot call #{method} on Animal"
  end
end

=> Animal.new.say_moo 
> "Cannot call say_moo on Animal"

Używając brakującej metody

class Animal
  def method_missing(method, *args, &block)
    say, speak = method.to_s.split("_")
    if say == "say"
      speak
    else
      super
    end
  end
end

=> a = Animal.new
=> a.say_moo
=> "moo"
=> a.shout_moo
=> NoMethodError: undefined method `shout_moo'

Użyj z blokiem

class Animal
  def method_missing(method, *args, &block)
    if method.to_s == 'say'
      block.call
    else
      super
    end
  end
end

 => Animal.new.say{ 'moo' }
 => "moo" 

Użyj z parametrem

class Animal
  def method_missing(method, *args, &block)
    say, speak = method.to_s.split("_")
    if say == "say" && speak
      return speak.upcase if args.first == "shout"
      speak
    else
      super
    end
  end
end

=> Animal.new.say_moo
=> "moo" 
=> Animal.new.say_moo("shout")
=> "MOO" 


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow