1

I was following the Action Mailer guideon https://guides.rubyonrails.org/action_mailer_basics.html#calling-the-mailer

I did almost the same of what tutorial show. The controller:

def create
  @user = User.create(user_params)

  if @user && UserMailer.with(user: @user).welcome_email.deliver_later
     token = encode_token({ user_id: @user.id })
     render json: { token: token }, status: :created
  else
     render json: @user.errors.messages, status: :bad_request
  end
end

The Mailer:

class UserMailer < ApplicationMailer
  default from: 'notifications@example.com'

  def welcome_email
    @user = params[:user]
    @url  = 'http://example.com/login'
    mail(to: @user.email, subject: 'Welcome to My Awesome Site')
  end
end

But when I make the request Active Job yells:

ActiveJob::SerializationError => "Unsupported argument type: User"

It works correctly using deliver_now

This shows that we have a problem with :async adapter. But as the guide says:

Active Job's default behavior is to execute jobs via the :async adapter. So, you can use deliver_later to send emails asynchronously. Active Job's default adapter runs jobs with an in-process thread pool. It's well-suited for the development/test environments, since it doesn't require any external infrastructure, but it's a poor fit for production since it drops pending jobs on restart. If you need a persistent backend, you will need to use an Active Job adapter that has a persistent backend (Sidekiq, Resque, etc).

So what I'm missing here?

João Ramires
  • 723
  • 10
  • 23
  • can you share your method code as well? – Gagan Gupta Mar 16 '21 at 20:13
  • The Mailer you say? – João Ramires Mar 16 '21 at 20:17
  • yeah.. btw if you can just pass the id in the code `with(user_id: @user.id)` and find the user inside mailer method like `@user = User.find(params[:user_id])`, it will work. Try and let me know. – Gagan Gupta Mar 16 '21 at 20:20
  • It didn't work. The error yielded now is: "Unsupported argument type: BSON::ObjectId" – João Ramires Mar 16 '21 at 20:22
  • Reading the API, https://edgeapi.rubyonrails.org/classes/ActiveJob/SerializationError.html, I see this: `Also raised when trying to serialize an object which can't be identified with a GlobalID - such as an unpersisted Active Record model.` This can be caused cuz i'm not using Active Record? – João Ramires Mar 16 '21 at 20:23
  • read this answer: https://stackoverflow.com/a/40896988/5832250 – Gagan Gupta Mar 16 '21 at 20:23
  • Ye I see this before. But this is not my case. I'm following 99.9% of the code in the guide. So it should work.. I think. – João Ramires Mar 16 '21 at 20:25
  • Try this.. may be it can help. send the object as json and retrieve the id value, then use `@user = User.find(params[:user_id])` in welcome_mailer. – Gagan Gupta Mar 16 '21 at 20:25
  • It's not working because ActiveJob doesn't support the objects. To make it accessible you have to either convert it into json string and then deserialise in the mailer method. – Gagan Gupta Mar 16 '21 at 20:27
  • Also, you can take a look on these answers. https://stackoverflow.com/q/27898183/5832250 – Gagan Gupta Mar 16 '21 at 20:29
  • It worked! Thanks! Please write an answer so I can accept it. Just adjusted to `params[:user]["_id"]["$oid"]` since I'm using Mongoid :) – João Ramires Mar 16 '21 at 20:29
  • 1
    That's great! keep it up.. – Gagan Gupta Mar 16 '21 at 20:31

1 Answers1

1

It's not working because ActiveJob doesn't support the objects. To make it accessible you have to either convert it into json string and then deserialise in the mailer method.

Try sending the object as json string and retrieve the id value, then use:

@user = User.find(params[:user_id])

Another approach is to use Resque or Sidekiq to process these jobs. They come really handy.

Another sources to help people out:

https://stackoverflow.com/a/40896988/5832250

If you want to go with rails guides and learn more:

https://guides.rubyonrails.org/active_job_basics.html#globalid

Gagan Gupta
  • 1,189
  • 7
  • 19