当邮件程序没有定义为这样的类方法时,你如何调用邮件程序中的类方法?

12

在Rails中发送邮件时,通常会这样做:

UserMailer.password_reset(user).deliver

但是如果我们查看UserMailer的内部,会发现这样的代码:

def password_reset(user) # not self.password_reset
  # ...
end

注意方法名称没有以self作为前缀。看起来,你需要先实例化对象如下所示。Rails是如何做到这一点的呢?

注意方法名称没有以self作为前缀。看起来,你需要先实例化对象如下所示。Rails是如何做到这一点的呢?

UserMailer.new.password_reset(user).deliver
2个回答

12

谢谢。但是为什么不把它变成类方法呢?从这种方法中我们获得了什么? - dee
我不确定我完全理解。你的意思是为什么不将它作为实例方法呢?这样,就像UserMailer.new.password_reset(user).deliver一样? - Rebitzele
我的意思是为什么要使用method missing?保持UserMailer.password_reset(user).deliver不变,但将def method更改为def self.method - dee
deliver已在ActionMailer模块中定义为类方法,请参见我的回答。 - Anand Shah
我并不完全理解这里的所有设计决策,但是如果你检查源代码,会发现幕后有很多事情在进行。似乎他们正在创建邮件程序的新实例,并且需要使用method_missing来完成,因为你的类方法无法做到这一点。我认为最好的方法是自己深入研究源代码。希望能对你有所帮助。 - Rebitzele

0
请注意,self.deliver方法已被弃用,请查看下面给出的代码。由于deliver方法被定义为类方法,因此您不必实例化邮件发送器类。

action_mailer/deprecated_api.rb

module ActionMailer
  module DeprecatedApi #:nodoc:
  extend ActiveSupport::Concern

  module ClassMethods
  # Deliver the given mail object directly. This can be used to deliver
  # a preconstructed mail object, like:
  #
  #   email = MyMailer.create_some_mail(parameters)
  #   email.set_some_obscure_header "frobnicate"
  #   MyMailer.deliver(email)
  def deliver(mail, show_warning=true)
    if show_warning
      ActiveSupport::Deprecation.warn "#{self}.deliver is deprecated, call " <<
        "deliver in the mailer instance instead", caller[0,2]
    end

    raise "no mail object available for delivery!" unless mail
    wrap_delivery_behavior(mail)
    mail.deliver
    mail
  end

发送邮件
一旦定义了邮件操作和模板,您可以传递消息或创建并保存以便稍后传递:
mail = Notifier.welcome(david)  # => a Mail::Message object
mail.deliver  # sends the email

#Above 2 steps can be combined
Notifier.welcome(david).deliver

你不需要实例化你的邮件类。相反,你只需在类本身上调用你定义的方法。
方法“password_reset”返回一个Mail::Message对象,然后可以只需告诉它执行deliver方法来发送邮件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接