为什么我可以在 rails 中的 ActionMailer::MessageDelivery 上使用已删除的 "deliver" 方法 6

Why can I use deleted "deliver" method on ActionMailer::MessageDelivery in rails 6

irb(main)> Rails.version
=> "6.0.3.3"

irb(main)> AwesomeNotifier.send_recommend_notification(self).method(:deliver).owner
AwesomeNotifier#send_recommend_notification: processed outbound mail in 0.2ms
=> ActionMailer::MessageDelivery

irb(main)> AwesomeNotifier::MessageDelivery.instance_methods(false)
=> [:deliver_later!, :deliver_later, :deliver_now!, :deliver_now, :message, :processed?, :__setobj__, :__getobj__]

看起来 ActionMailer::MessageDelivery 中没有 deliver 方法 因为它在 5.0 commit here
上删除了 但它以某种方式起作用。

这是哪里来的deliver??
我应该使用 deliver_laterdeliver_now 但我想说清楚 deliver 是什么。

AwesomeNotifier::MessageDelivery 是委托对象——也就是说,它是另一个对象的包装器;虽然它提供了自己的方法,但如果您在其上调用未明确定义的方法,消息将传递给它包装的对象。

来自docs

The ActionMailer::MessageDelivery class is used by ActionMailer::Base when creating a new mailer. MessageDelivery is a wrapper (Delegator subclass) around a lazy created Mail::Message.

虽然 MessageDelivery 定义了 deliver_laterdeliver_now,但调用 deliver 实际上会将调用置于 Mail::Message 的实例上。其实现是 here.

我怀疑由于历史原因委托人模式保留在这个实例上,并且可能有 Rails 代码依赖于 MessageDelivery 上可用的某些 Mail::Message 方法。但它可能会导致混淆 MessageDelivery 实际响应哪些方法以及它的预期行为可能是什么。

在您自己的代码中,如果您曾经确实需要直接访问消息,使用 MessageDelivery 的 #message 方法来显式引用可能会更清楚消息。