Home > Software engineering >  Mailer method returns unexpected ActionMailer::Base::NullMail
Mailer method returns unexpected ActionMailer::Base::NullMail

Time:09-28

I am new to Rubyand also not good at OOP. I have a class like this

class Workflow::Mailer < ActionMailer::Base
    def unapproved_remind_mail(args)
        return [
            {
                "uid": "1060_424652",
                "noticecd": "A002",
                "ref_url": "",
                "title": "",
                "content": ""
            },
            {
                "uid": "1060_403595",
                "noticecd": "A002",
                "ref_url": "",
                "title": "",
                "content": ""
            }
        ].to_json
    end

    def self.send_unapproved_remind_mails(args)
        args = args.dup
        sm_body = unapproved_remind_mail(args)
        Rails.logger.fatal("sm_body: #{sm_body}")
    end
end

when I call function Workflow::Mailer.send_unapproved_remind_mails it logs sm_body: #<ActionMailer::Base::NullMail:0x000055f289ff5ad8> instead of the hash object. Is there anyway to fix this?

Edit: I also want to call a private method inside unapproved_remind_mail

CodePudding user response:

app/mailers/workflow/mailer.rb

class Workflow::Mailer < ActionMailer::Base
  default from: "[email protected]"
  # layout 'mailer'

  def send_unapproved_remind_mails(args)
    @sm_body = unapproved_remind_mail(args)
    Rails.logger.fatal("sm_body: #{@sm_body}")

    mail(
      subject: "Email Subject",
      to: "[email protected]"
    )
  end

  private

  def unapproved_remind_mail(args)  # args param should be used in the method body, otherwise define it as parameterless method
    return [
      {
        "uid": "1060_424652",
        "noticecd": "A002",
        "ref_url": "",
        "title": "",
        "content": ""
      },
      {
        "uid": "1060_403595",
        "noticecd": "A002",
        "ref_url": "",
        "title": "",
        "content": ""
      }
    ].to_json
  end
end

app/views/workflow/mailer/send_unapproved_remind_mails.html.erb

// your email body...

Output:

sm_body: [{"uid":"1060_424652","noticecd":"A002","ref_url":"","title":"","content":""},{"uid":"1060_403595","noticecd":"A002","ref_url":"","title":"","content":""}]
  Rendering workflow/mailer/send_unapproved_remind_mails.html.erb
  Rendered workflow/mailer/send_unapproved_remind_mails.html.erb (Duration: 1.0ms | Allocations: 182)
Workflow::Mailer#send_unapproved_remind_mails: processed outbound mail in 62.7ms
#<Mail::Message:97340, Multipart: false, Headers: <From: from@example.com>, <To: to@example.com>, <Subject: Email Subject>, <Mime-Version: 1.0>, <Content-Type: text/html>>

CodePudding user response:

A Rails mailer defines instance methods which generate the email by calling mail, e.g.:

# app/mailers/workflow_mailer.rb

class WorkflowMailer < ActionMailer::Base
  def unapproved_remind_mail(address)
    mail(to: address)
  end
end

You typically have a view that returns the email body:

# app/views/workflow_mailer.text.erb

Hello, this is your reminder.

To send the email, you call deliver_now / deliver_later:

WorkflowMailer.unapproved_remind_mail('[email protected]').deliver_now

Note that unapproved_remind_mail is called in a very unusual way: despite being an instance method, you call the method on the class itself. This is something Rails came up with to ... make things easier I suppose.

To fetch additional data for the email body from another method, you can add a private helper and assign its result to an instance method, e.g.:

class WorkflowMailer < ActionMailer::Base
  def unapproved_remind_mail(address)
    @json_data = json_data
    mail(to: address)
  end

  private

  def json_data
    { foo: 123 }.to_json
  end
end

Which can be used in the view:

# app/views/workflow_mailer.text.erb

Hello, this is your reminder.

<%= @json_data %>
  • Related