如果没有这样定义,你怎么能在邮件程序上调用类方法呢?

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

UserMailer.password_reset(user).deliver 

但是,如果我们查看UserMailer我们可以看到:

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

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

 UserMailer.new.password_reset(user).deliver 

这是一个很好的问题。 在源代码( https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb )中,Rails使用method_missing创建ActionMailer的新实例。 以下是来源的相关摘录:

 def method_missing(method_name, *args) # :nodoc: if respond_to?(method_name) new(method_name, *args).message else super end end 

请注意,不推荐使用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对象,然后可以告诉传递将其自身发送出去。