首页 > 解决方案 > 如何从 Rails 控制台发送电子邮件:NoMethodError(nil:NilClass 的未定义方法 `email')

问题描述

在添加到保存后发送的欢迎电子邮件后,我正在尝试向现有订阅者发送时事通讯。假设我想将这封欢迎电子邮件发送给现有订阅者,并且我只需要此功能一次。我正在寻找一种从 Rais 控制台发送此电子邮件的方法。我收到“电子邮件”的 NoMethodError,请花点时间查看下面的代码。

# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
  default from: 'hello@example.com'
  layout 'bootstrap-mailer'

  def welcome_email
    @newsletter = params[:newsletter]
    @url  = root_url
    attachments.inline['welcome.png'] = File.read(Rails.root + 'welcome.png')
    make_bootstrap_mail(
      to: @newsletter.email,
      subject: '‍♀️ Welcome to My Newsletter!‍'
    )
  end

end

然后从 Rails 控制台调用 welcome_email

$ rails c
Running via Spring preloader in process 10333
Loading development environment (Rails 6.0.3.3)
>> def self.send(newsletter)
>> @newsletters = Newsletter.all
>> @newsletters.each do |newsletter|
?> UserMailer.with(newsletter: @newsletter).welcome_email.deliver_now
>> end
>> end
=> :send
>> send(@newsletters)
  Newsletter Load (0.5ms)  SELECT "newsletters".* FROM "newsletters"
UserMailer#welcome_email: processed outbound mail in 9.6ms
Traceback (most recent call last):
        5: from (irb):10
        4: from (irb):10:in `rescue in irb_binding'
        3: from (irb):3:in `send'
        2: from (irb):4:in `block in send'
        1: from app/mailers/user_mailer.rb:11:in `welcome_email'
NoMethodError (undefined method `email' for nil:NilClass)

当我运行$ Newsletter.all它返回现有的电子邮件

Newsletter.all
  Newsletter Load (0.4ms)  SELECT "newsletters".* FROM "newsletters" LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Newsletter id: 1, email: "email-1@example.com", created_at: "2020-09-17 21:59:23", updated_at: "2020-09-17 21:59:23">, #<Newsletter id: 15, email: "email-2@example.com", created_at: "2020-09-18 01:20:46", updated_at: "2020-09-18 01:20:46">, #<Newsletter id: 16, email: "email-3@example.com", created_at: "2020-09-18 20:51:21", updated_at: "2020-09-18 20:51:21">]>

如何正确地将这些电子邮件传递给 welcom_email?我正在使用 bootstrap-email gem,它在 newsletter.save 上正确发送welcome_email。

# app/controllers/newsletters_controller.rb
class NewslettersController < ApplicationController

    def new
        @newsletter = Newsletter.new
    end

    def create
        @newsletter = Newsletter.new(newsletter_params)
        if @newsletter.save
        UserMailer.with(newsletter: @newsletter).welcome_email.deliver_now
            flash[:success] = "You've successfully subscribed to our newsletter. You will recive confirmation email with instractions in a few minuets."
            redirect_to root_path
        else
            redirect_to root_path, alert: "Email address already subscribed to newsletter or incorrect format."
        end
    end

    private

    def newsletter_params
        params.require(:newsletter).permit(:email)
    end

end

这是从创建方法发送电子邮件的开发日志

Started POST "/newsletters" for ::1 at 2020-09-20 13:00:02 -0700
Processing by NewslettersController#create as HTML
  Parameters: {"authenticity_token"=>"bSR/L+5IQB027LeCv42DX3tw120NkLPmNHMPGqFSiOK66ct8Z2N7Yx5XbBVMmbFNgVoKKoSQCPaOoKWkC+AHvg==", "newsletter"=>{"email"=>"email-4@example.com"}, "commit"=>"Subscribe to Newsletter!"}
  [1m[35m (0.2ms)[0m  [1m[35mBEGIN[0m
  ↳ app/controllers/newsletters_controller.rb:9:in `create'
  [1m[36mNewsletter Exists? (1.0ms)[0m  [1m[34mSELECT 1 AS one FROM "newsletters" WHERE LOWER("newsletters"."email") = LOWER($1) LIMIT $2[0m  [["email", "email-4@example.com"], ["LIMIT", 1]]
  ↳ app/controllers/newsletters_controller.rb:9:in `create'
  [1m[36mNewsletter Create (2.4ms)[0m  [1m[32mINSERT INTO "newsletters" ("email", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"[0m  [["email", "email-4@example.com"], ["created_at", "2020-09-20 20:00:03.020983"], ["updated_at", "2020-09-20 20:00:03.020983"]]
  ↳ app/controllers/newsletters_controller.rb:9:in `create'
  [1m[35m (0.7ms)[0m  [1m[35mCOMMIT[0m
  ↳ app/controllers/newsletters_controller.rb:9:in `create'
  Rendering user_mailer/welcome_email.html.erb within layouts/bootstrap-mailer
  Rendered user_mailer/welcome_email.html.erb within layouts/bootstrap-mailer (Duration: 7.8ms | Allocations: 6866)
  Rendering user_mailer/welcome_email.text.erb
  Rendered user_mailer/welcome_email.text.erb (Duration: 0.7ms | Allocations: 128)
UserMailer#welcome_email: processed outbound mail in 531.1ms
Delivered mail 5f67b4c38a48f_5ba63fd8c7a7684c6726@PC.local.mail (3513.0ms)
Date: Sun, 20 Sep 2020 13:00:03 -0700
From: hello@example.com
To: email-4@example.com
Message-ID: <5f67b4c38a48f_5ba63fd8c7a7684c6726@pc.local.mail>
Subject: =?UTF-8?Q?=F0=9F=99=8B=F0=9F=8F=BB=E2=80=8D=E2=99=80=EF=B8=8F=F0=9F=A6=84?=
 =?UTF-8?Q?_Welcome_to_Newsletter!=E2=80=8D?=
Mime-Version: 1.0
Content-Type: multipart/related;
 boundary="--==_mimepart_5f67b4c3d687_5ba63fd8c7a7684c67176";
 charset=UTF-8
Content-Transfer-Encoding: 7bit

标签: ruby-on-railsrubyactionmailer

解决方案


我将@newsletter 替换为newsletter,UserMailer.with(newsletter: @newsletter).welcome_email.deliver_now然后它就起作用了。

从 Rails 控制台

>> def self.send(newsletter)
>> @newsletters = Newsletter.all
>> @newsletters.each do |newsletter|
?> UserMailer.with(newsletter: newsletter).welcome_email.deliver_now
>> end
>> end
>> send(@newsletters)
[1m[36mNewsletter Load (0.6ms)[0m  [1m[34mSELECT "newsletters".* FROM "newsletters"[0m
 Rendering user_mailer/welcome_email.html.erb within layouts/bootstrap-mailer
 Rendered user_mailer/welcome_email.html.erb within layouts/bootstrap-mailer (Duration: 27.2ms | Allocations: 6172)
 Rendering user_mailer/welcome_email.text.erb
 Rendered user_mailer/welcome_email.text.erb (Duration: 0.5ms | Allocations: 129)
UserMailer#welcome_email: processed outbound mail in 876.2ms
Delivered mail 5f67c372b64d3_76d23ff23d83204c25077@PC.local.mail (518.1ms)

# Welcome email sent to each email in Newsletter

与我的时事通讯控制器中的 create 方法不同,我在控制台中的代码没有 @newsleeter,因为注释中指出 @mu 太短了。

瞧!我们现在知道如何从 Rails 控制台手动为数据库中的所有现有电子邮件发送电子邮件。


推荐阅读