chickensmitten
chickensmitten

Reputation: 495

Rails 4.2 Active Job Resque Enqueue Undefined Method Issue

I am following https://blog.engineyard.com/2014/getting-started-with-active-job to implement Active Job in Rails 4.2. But faced with the following issue in Resque. Error reads:

Worker
ChickenSmitten.local:64238 on EMAIL at just now Retry or Remove
Class
 ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper
Arguments
---
job_class: PasswordResetJob
job_id: 35f70043-9a9b-4add-8700-a5f388350fb4
queue_name: email
arguments:
- [email protected]
Exception
NoMethodError
Error
undefined method `email' for "[email protected]":String

My codes are below:

password_resets_controller.rb

  def create
    @user = User.find_by(email: params[:password_reset][:email].downcase)
    if @user
      @user.create_reset_digest
      @user.send_password_reset_email
      flash[:notice] = "Email sent with password reset instructions"
      redirect_to root_url
    else
      flash.now[:error] = "Email address not found"
      render 'new'
    end
  end

user.rb

  def send_password_reset_email
    PasswordResetJob.new(self.email).enqueue(wait: 10.seconds)
  end  

app/jobs/password_reset_job.rb

class PasswordResetJob < ActiveJob::Base
  queue_as :email

  def perform(email)
    UserMailer.password_reset(email).deliver_now
  end
end

app/mailers/user_mailer.rb

class UserMailer < ActionMailer::Base
  default from: "[email protected]"

  def password_reset(user)
    @user = user
    mail to: user.email, subject: "Password Reset"
  end

end

Somehow, "self.email" from user.rb is not passed to password_reset_job.rb. Hence, error "undefined method `email' for "[email protected]":String".

Thanks in advance.

UPDATE

Pursuant to Prakash's advice and making one more change as below, changed "self.email" to "self":

  def send_password_reset_email
    PasswordResetJob.new(self).enqueue(wait: 10.seconds)
  end 

A new error popped. Here is the error:

ActionView::Template::Error
No route matches {:action=>"edit", :controller=>"password_resets", :email=>"[email protected]", :format=>nil, :id=>nil} missing required keys: [:id]

Below are more details that may help.

[2] pry(#<User>)> PasswordResetJob.new(self).enqueue(wait: 10.seconds)
[ActiveJob] Enqueued PasswordResetJob (Job ID: 6bdcca3c-367d-48ea-b3c9-1f5378e5df57) to Resque(email) at 2015-01-06 04:58:28 UTC with arguments: gid://affiliation/User/1
=> #<PasswordResetJob:0x007fbd4c028dc8
 @arguments=
  [#<User:0x007fbd4b686590
    id: 1,
    username: "bob",
    email: "[email protected]",
    password_digest: "$2a$10$dbbEBwNgBtaZEvtl7EsUm./hdukr3MMKlUWdouV3RwIFMmMPfR6CS",
    created_at: Thu, 01 Jan 2015 03:38:54 UTC +00:00,
    updated_at: Tue, 06 Jan 2015 04:58:01 UTC +00:00,
    role: "admin",
    slug: "bob",
    activation_digest: "$2a$10$wdoO7vn5Ng4U4TEPCmqVFeVYAB8sZ2CKEpVFfduYyD7Ee.NfvSRsi",
    activated: true,
    activated_at: Thu, 01 Jan 2015 03:41:19 UTC +00:00,
    remember_digest: nil,
    reset_digest: "$2a$10$Eu1jYllohAY2IQO4Uc.0TuyNmRWWuu3jQgjZrIZLwFlo1t8n1hNZO",
    reset_sent_at: Tue, 06 Jan 2015 04:58:01 UTC +00:00,
    url: "www.google.com",
    bio: "Woo ga shaka.">],
 @job_id="6bdcca3c-367d-48ea-b3c9-1f5378e5df57",
 @queue_name="email",
 @scheduled_at=1420520308.6658938>

views/user_mailer/password_reset.html.rb

<h1>Password reset</h1>

<p>To reset your password click the link below:</p>

<%= link_to "Reset password", edit_password_reset_url(@user.reset_token,
                                                      email: @user.email) %>

<p>This link will expire in two hours.</p>

<p>
If you did not request your password to be reset, please ignore this email and
your password will stay as it is.
</p>

Upvotes: 2

Views: 2691

Answers (2)

Cristian Bica
Cristian Bica

Reputation: 4117

You are passing the email to PasswordResetJob which passes it to the mailer but the mailer expects a User instance.

PS: you can do directly UserMailer.password_reset(self.email).deliver_later in the model. See http://api.rubyonrails.org/classes/ActionMailer/MessageDelivery.html#method-i-deliver_later

Upvotes: 1

Prakash Murthy
Prakash Murthy

Reputation: 13067

def perform(email)
  UserMailer.password_reset(email).deliver_now
end

This is calling the password_reset method in UserMailer with email (which has the value of [email protected] in this specific case.

def password_reset(user)
  @user = user
  mail to: user.email, subject: "Password Reset"
end

So within password_reset method, user is getting set to [email protected], and hence failing when user.email is called.

One way to fix this would be to make the method as follows:

app/mailers/user_mailer.rb

class UserMailer < ActionMailer::Base
  default from: "[email protected]"

  def password_reset(email)
    mail to: email, subject: "Password Reset"
  end

end

You might have to find a different way based on the specific needs.

Upvotes: 0

Related Questions