Поиск…


параметры

параметр подробности
метод Имя метода, который был вызван (в приведенном выше примере это :say_moo , обратите внимание, что это символ.
* арг Аргументы, переданные этому методу. Может быть любое число, или нет
и блок Блок вызванного метода может быть либо блоком do , либо { } закрытым блоком

замечания

Всегда вызывайте super, в нижней части этой функции. Это экономит молчащий сбой, когда что-то вызывается, и вы не получаете ошибку.

Например, метод method_missing вызовет проблемы:

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 - хороший инструмент для использования, когда это необходимо, но имеет две затраты, которые вы должны учитывать. Во-первых, method_missing менее эффективен - рубин должен искать класс и всех его предков, прежде чем он сможет отступить от этого подхода; этот штраф исполнения может быть тривиальным в простом случае, но может складываться. Во-вторых, в общем, это форма метапрограммирования, которая обладает большой властью, которая несет ответственность за обеспечение безопасной реализации, правильную обработку вредоносных входов, неожиданные входы и т. Д.

Вы также должны переопределить respond_to_missing? вот так:

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

Улавливание вызовов неопределенным методом

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"

Использование отсутствующего метода

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'

Использовать с блоком

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" 

Использовать с параметром

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow