何时使用`method_missing`

tok*_*khi 8 ruby metaprogramming

在下面的代码中,方法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!!!
Run Code Online (Sandbox Code Playgroud)

在哪些情况下我应该如何使用它method_missing?使用安全吗?

tad*_*man 9

如果您以预期的方式使用它并且不会被带走,那么使用它是完全安全的.毕竟,并非你所能做的一切都值得做.

优点method_missing是你可以用独特的方式回应各种事物.

缺点是你没有宣传你的能力.其他期望您使用respond_to?某些东西的对象将无法获得确认,并且可能会以您不想要的方式处理您的自定义对象.

为了构建领域特定语言并在组件之间提供非常松散的粘合剂,这种东西是非常宝贵的.

Ruby OpenStruct类就是一个很好的例子.

  • 实际上,`method_missing`的孪生兄弟是`respond_to_missing?`你应该*总是*一起覆盖它们. (8认同)

Ser*_*sev 8

总结:何时使用?它会让你的生活更轻松,而不会使他人的生活变得复杂.


这是一个浮现在脑海中的例子.它来自redis_failover gem.

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

在这里,我们检查调用的方法是否实际上是redis连接的命令.如果是这样,我们将其委托给底层连接.如果没有,转发到超级.

另一个着名的method_missing应用示例是ActiveRecord finders.

User.find_by_email_and_age('me@example.com', 20)
Run Code Online (Sandbox Code Playgroud)

当然,没有一种方法find_by_email_and_age.相反,method_missing打破名称,分析部件并find使用适当的参数调用.