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

时间:2022-01-31 21:12:55

When sending mail in Rails, usually one would do something like this:

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

UserMailer.password_reset(user).deliver

But if we look inside UserMailer we can see this:

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

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

Notice that the method name is not prefixed with self. Looking at it, it seems like you need to instantiate the object first as below. How does Rails do this?

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

UserMailer.new.password_reset(user).deliver

2 个解决方案

#1


11  

That's a great question. In the source (https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb), Rails uses method_missing to create a new instance of the ActionMailer. Here's the relevant excerpt from the source:

这是一个很好的问题。在源代码(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

#2


0  

Please note that the self.deliver method is deprecated, have a look at the code given below. Since deliver method is defined as a class method you don't have to instantiate the mailer class.

请注意,不推荐使用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

Sending mail

Once a mailer action and template are defined, you can deliver your message or create it and save it for delivery later:

定义邮件程序操作和模板后,您可以传递邮件或创建邮件并保存以供日后交付:

mail = Notifier.welcome(david)  # => a Mail::Message object
mail.deliver  # sends the email

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

You never instantiate your mailer class. Rather, you just call the method you defined on the class itself.

您永远不会实例化您的邮件程序类。相反,您只需调用您在类本身上定义的方法。

The method password_reset returns a Mail::Message object which can then just be told deliver to send itself out.

password_reset方法返回一个Mail :: Message对象,然后可以告诉传递将其自身发送出去。

#1


11  

That's a great question. In the source (https://github.com/rails/rails/blob/master/actionmailer/lib/action_mailer/base.rb), Rails uses method_missing to create a new instance of the ActionMailer. Here's the relevant excerpt from the source:

这是一个很好的问题。在源代码(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

#2


0  

Please note that the self.deliver method is deprecated, have a look at the code given below. Since deliver method is defined as a class method you don't have to instantiate the mailer class.

请注意,不推荐使用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

Sending mail

Once a mailer action and template are defined, you can deliver your message or create it and save it for delivery later:

定义邮件程序操作和模板后,您可以传递邮件或创建邮件并保存以供日后交付:

mail = Notifier.welcome(david)  # => a Mail::Message object
mail.deliver  # sends the email

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

You never instantiate your mailer class. Rather, you just call the method you defined on the class itself.

您永远不会实例化您的邮件程序类。相反,您只需调用您在类本身上定义的方法。

The method password_reset returns a Mail::Message object which can then just be told deliver to send itself out.

password_reset方法返回一个Mail :: Message对象,然后可以告诉传递将其自身发送出去。