当使用`method_missing`(When to use `method_missing`)

2019-08-03 16:19发布

在下面的代码,方法roar未在类中定义的Lion ,但仍可以使用称为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 ? 而且是可以安全使用?

Answer 1:

这是使用所提供完全安全的 ,你预期的方式使用它,不要得意忘形。 并非一切都可以做的是值得做的,毕竟。

的优势method_missing是,你可以在独特的方式各种各样的事情作出回应。

缺点是你不做广告你的能力。 那希望你对其他对象respond_to? 事情不会得到确认,可能对待你的自定义对象在你不打算的方式。

对于建筑领域特定语言,并提供非常宽松的胶体成分之间,这样的事情是非常宝贵的。

在哪里,这是一个不错的选择一个很好的例子是Ruby OpenStruct类。



Answer 2:

总结:何时使用? 当它会让你的生活更轻松他人的生活不复杂。


下面是弹出想到一个例子。 这是从redis_failover宝石。

# 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的连接的命令。 如果是这样,我们把它委托给底层连接(一个或多个)。 如果不是,继电器超。

另一个著名的例子method_missing应用是ActiveRecord的发现者。

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

这里没有,当然,方法find_by_email_and_age 。 相反, method_missing打破了名字,分析了零件,并调用find适当的参数。



Answer 3:

这里是我的最爱

class Hash
  def method_missing(sym,*args)
    fetch(sym){fetch(sym.to_s){super}}
  end
end

它允许就好像它们是属性的哈希我访问值。 使用JSON数据时,这是特别方便。

因此,例如,而不是写tweets.collect{|each|each['text']}我可以只写tweets.collect(&:text) ,其是要短得多。 也或者,而不是tweets.first['author']我可以只写tweets.first.author这感觉更自然。 实际上,它给你的Javascript式访问哈希值。

 

NB, 我期待的猴子在我家门口修补警方任何一分钟...



Answer 4:

首先,坚持塞尔吉奥Tulentsev的总结。

除此之外,我觉得看的例子是获得正确和错误的情况下,感觉最好的方式method_missing ; 所以这里是另外一个简单的例子:


我最近使用method_missing在一个空对象 。

  • 该空对象是一阶模型的替代品。

  • 该命令存储不同价格不同货币。


如果没有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_xxx属性Order



Answer 5:

我还发现,从(保罗·佩罗塔)博客文章在那里证明时使用的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)


文章来源: When to use `method_missing`