【问题标题】:Rails 4.2 Active Job Resque Enqueue Undefined Method IssueRails 4.2 Active Job Resque Enqueue Undefined Method 问题
【发布时间】:2015-03-03 17:42:11
【问题描述】:

我正在关注https://blog.engineyard.com/2014/getting-started-with-active-job 在 Rails 4.2 中实现 Active Job。但在 Resque 中面临以下问题。错误读取:

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:
- bob@example.com
Exception
NoMethodError
Error
undefined method `email' for "bob@example.com":String

我的代码如下:

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

用户.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: "noreply@example.com"

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

end

不知何故,来自 user.rb 的“self.email”没有传递给 password_reset_job.rb。因此,“bob@example.com”的错误“未定义方法`email':String”。

提前致谢。

更新

根据 Prakash 的建议并进行如下更改,将“self.email”更改为“self”:

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

弹出一个新错误。这是错误:

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

以下是可能有所帮助的更多详细信息。

[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: "bob@example.com",
    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>

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 resque rails-activejob


    【解决方案1】:

    您将电子邮件传递给 PasswordResetJob,后者将其传递给邮件程序,但邮件程序需要一个用户实例。

    PS:你可以直接在模型中做 UserMailer.password_reset(self.email).deliver_later。见http://api.rubyonrails.org/classes/ActionMailer/MessageDelivery.html#method-i-deliver_later

    【讨论】:

    • 您的回答帮助我解决了这个问题中所述的问题,但出现了一个新错误,如上面的更新所示。我想应该将新错误作为一个新问题提出。会看看我能做什么。同时,请让我知道是否可以帮助解决此错误。我非常感激。谢谢。 =)
    • 在 edit_password_reset_url 中,路由助手需要 :id 而 :id 为 nil。 :id 是第一个参数,所以这可能意味着“@user.reset_token”为 nil
    • 没错,也许是这样,这里有一些其他的观察结果可能会有所帮助。 (1) 如果我不使用后台作业,而只在“def send_password_reset_email”中使用“UserMailer.password_reset(self).deliver”,而所有其他代码保持不变,则不会出现错误并且将发送电子邮件。但当然,这不是最好的方法。 (2) 这更难,因为即使远程撬动我也无法撬动“/password_reset.html.rb”。关于我如何做到这一点的任何想法?再次感谢。
    【解决方案2】:
    def perform(email)
      UserMailer.password_reset(email).deliver_now
    end
    

    这是用email 调用UserMailer 中的password_reset 方法(在这种特定情况下,其值为bob@example.com

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

    所以在password_reset 方法中,user 被设置为bob@example.com,因此在调用user.email 时失败。

    解决此问题的一种方法是使方法如下:

    app/mailers/user_mailer.rb

    class UserMailer < ActionMailer::Base
      default from: "noreply@example.com"
    
      def password_reset(email)
        mail to: email, subject: "Password Reset"
      end
    
    end
    

    您可能需要根据具体需求寻找不同的方式。

    【讨论】:

    • 嘿,谢谢。错误不再存在,但我遇到了一个新错误,ActionView::Template::Error No route matches {:action=>"edit", :controller=>"password_resets", :email=>"bob@ example.com", :format=>nil, :id=>nil} 缺少必需的键:[:id]。我已经为此更新了我的帖子,错误。
    • 请为新问题创建一个新问题;用出现的下一个问题更新现有问题不是一个好习惯。
    • 同意。很快就会发布。
    猜你喜欢
    • 2015-03-04
    • 2015-01-27
    • 2014-03-17
    • 2016-02-15
    • 2011-04-26
    • 1970-01-01
    • 2014-11-06
    • 2015-07-07
    • 2013-08-31
    相关资源
    最近更新 更多