8

以下のコードでは、 methodroarは classLionで定義されていませんが、 を使用して呼び出すことができますmethod_missing

class Lion
  def method_missing(name, *args)
    puts "Lion will #{name}: #{args[0]}"
  end
end

lion = Lion.new
lion.roar("ROAR!!!") # => Lion will roar: ROAR!!!

どのような状況で、どのように使用すればよいmethod_missingですか? また、安全に使用できますか?

4

5 に答える 5

9

期待どおりに使用し、夢中にならない限り、完全に安全に使用できます。結局のところ、できることすべてに価値があるわけではありません。

の利点はmethod_missing、あらゆる種類のものに独自の方法で対応できることです。

不利な点は、自分の能力を宣伝しないことです。何かを期待する他のオブジェクトはrespond_to?確認を取得せず、意図しない方法でカスタム オブジェクトを処理する可能性があります。

ドメイン固有言語を構築し、コンポーネント間の非常に緩い接着剤を提供するために、この種のことは非常に貴重です。

これが適している例として、Ruby OpenStructクラスがあります。

于 2012-12-07T09:11:27.017 に答える
8

要約:いつ使用するか?それがあなたの人生を楽にし、他の人の人生を複雑にしないとき。


これが頭に浮かぶ1つの例です。これはredis_failovergemからのものです。

# Dispatches redis operations to master/slaves.
def method_missing(method, *args, &block)
  if redis_operation?(method)
    dispatch(method, *args, &block)
  else
    super
  end
end

ここでは、呼び出されたメソッドが実際にredis接続のコマンドであるかどうかを確認します。その場合、基礎となる接続に委任します。そうでない場合は、スーパーに中継します。

アプリケーションのもう1つの有名な例method_missingは、ActiveRecordファインダーです。

User.find_by_email_and_age('me@example.com', 20)

もちろん、方法はありませんfind_by_email_and_age。代わりに、method_missing名前を壊し、パーツを分析して、find適切なパラメーターで呼び出します。

于 2012-12-07T09:07:54.057 に答える
4

何よりもまず、Sergio Tulentsev の要約に固執してください。

それとは別に、例を見ることは、 の正しい状況と間違った状況を感じ取るための最良の方法だと思いmethod_missingます。別の簡単な例を次に示します。


最近method_missingNull Objectで使用しました。

  • Null Object は Order モデルの代替品でした。

  • 注文は、異なる通貨の異なる価格を保存します。


それなしmethod_missingでは次のようになります。

class NullOrder
  def price_euro
    0.0
  end

  def price_usd
    0.0
  end

  # ...
  # repeat for all other currencies
end

を使用method_missingすると、次のように短縮できます。

class NullOrder
  def method_missing(m, *args, &block)  
    m.to_s =~ /price_/ ? 0.0 : super
  end
end

に新しい属性をNullOrder追加するときに を更新する (忘れずに) 必要がないという追加の利点があります。price_xxxOrder

于 2012-12-07T15:47:38.000 に答える
4
于 2012-12-07T09:11:51.323 に答える
3

(Paolo Perrotta) からのブログ投稿も見つけました。ここでは、method_missing をいつ使用するかを示しています。

class InformationDesk
  def emergency
    # Call emergency...
    "emergency() called"
  end

  def flights
    # Provide flight information...
    "flights() called"
  end

  # ...even more methods
end

ランチタイムにサービスを依頼したかどうかを確認します。

class DoNotDisturb
  def initialize
    @desk = InformationDesk.new
  end

  def method_missing(name, *args)
    unless name.to_s == "emergency"
      hour = Time.now.hour
      raise "Out for lunch" if hour >= 12 && hour < 14
    end

    @desk.send(name, *args)
  end
end

# At 12:30...
DoNotDisturb.new.emergency # => "emergency() called"
DoNotDisturb.new.flights # ~> -:37:in `method_missing': Out for lunch (RuntimeError)
于 2012-12-07T09:32:50.807 に答える