`method_missing&#39 ;:未定义的方法`mail' for Emailer:Class(NoMethodError)

时间:2018-05-06 14:58:37

标签: ruby-on-rails ruby actionmailer

我正在研究Peter Cooper的书“Beginning Ruby”。
有一个简单的例子,使用ActionMailer发送电子邮件。 示例代码如下:

require 'action_mailer'

ActionMailer::Base.smtp_settings = {
    :address => "smtp.mail.yahoo.com",
    :port => 465,
    :authentication => :login,
    :user_name => "username@yahoo.com",
    :password => "password",
    :openssl_verify_mode => :ssl
}

class Emailer < ActionMailer::Base
  def self.test_email(email_address, email_body)
    mail(to: email_address, from: 'username@yahoo.com', subject: 'action mailer test', body: email_body)
  end
end

Emailer.test_email('username@gmail.com', 'This is a test e-mail!').deliver_now

如您所见,我想使用yahoo的smtp服务器向我的Gmail帐户发送电子邮件。我向ActionMailer :: Base提供了所需的smtp setting并创建了类方法test_email,以便使用main方法和deliver_now方法发送电子邮件。但是,我收到以下错误消息:

/home/asarluhi/.rvm/gems/ruby-2.5.1@beginning_ruby/gems/actionmailer-5.2.0/lib/action_mailer/base.rb:582:in `method_missing': undefined method `mail' for Emailer:Class (NoMethodError)

我还尝试将test_email方法更改为实例方法并使用Emailer.new.test_email ...在这种情况下,我收到的错误消息是:

/home/asarluhi/.rvm/gems/ruby-2.5.1@beginning_ruby/gems/mail-2.7.0/lib/mail/message.rb:1396:in `method_missing': undefined method `deliver_now' for #<Mail::Message:0x0000000002e0eac8> (NoMethodError)

我不知道为什么方法mail首先然后方法deliver_now无法识别,而是Ruby 5.2.0中的两个方法都属于ActionMailer::Base

---编辑 -
如果我从self方法中移除test_email,就像它最初在书中一样(我认为这是一个错误),当我运行包含上述代码的rb文件时,我会收到一个很长的追溯(21 ()行,并显示以下错误消息:

/home/asarluhi/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/net/protocol.rb:189:in `rbuf_fill': end of file reached (EOFError)

根据作者,ActionMailer可以独立于Rails使用。 所以我在一个专用的rvm gemset中安装了ActionMailer gem,并将上面的代码写在一个rb文件中,代码是从书中提取的。运行此脚本我收到EOFError错误。我尝试使其工作的所有尝试,例如将self添加到test_email方法或在类Emailer的实例上调用方法test_email都失败了。

3 个答案:

答案 0 :(得分:1)

问题在于使用&#39; self&#39;。必须是

def test_email(email_address, email_body)
  ...
end

而不是

def self.test_email(email_address, email_body)
  ...
end

所以,Emailer.test_email.deliver_now会奏效。 docs我们可以看到mail是实例方法,但在self.method_name只有类方法可用。类方法是属于该类的一部分功能,但不依赖于任何特定的单个实例。反向陈述也是公平的。 为什么Emailer实例而不是类?它来自ActionMailer :: Base

答案 1 :(得分:1)

我没有要检查的雅虎帐户,但this configuration已使用我的Gmail帐户:

use Cro::HTTP::Client;

my $resp;
my $data = "";

if (%headers{'content-type'} // '') eq self.form_urlencoded {
    $data = oauth_query(%args);
} elsif (%headers{'content-type'} // '').contains('form-data') { # multipart/form-data
    $data = %args{'form-data'};
} else {
    $data = "";
}

my $client = Cro::HTTP::Client.new(headers =>  |%headers);

if $data {
    $resp = await $client.post: $url, body => |%args;
} else {
    $resp = await $client.get: $url;
}

return $resp;

答案 2 :(得分:0)

可能导致此错误消息的一种方法是,如果您只是使用了错误的命名空间,例如我有

AlertsMailer.new_user_signup(user).deliver_now

但对我来说应该是

MessagesMailer.new_user_signup(user).deliver_now

因此 rails 找不到该命名空间的方法。正如我所了解的那样,仔细检查您的代码是值得的:)