开发者

Rails: Absolutely stumped with delayed_job. Not receiving arguments anywhere

开发者 https://www.devze.com 2023-01-28 09:21 出处:网络
I\'m trying to send mail in a Rails 3 application using collectiveidea\'s delayed_job. If I try to send mail regularly (.deliver) it works fine, but as soon as I switch to delayed job, things fall to

I'm trying to send mail in a Rails 3 application using collectiveidea's delayed_job. If I try to send mail regularly (.deliver) it works fine, but as soon as I switch to delayed job, things fall to pieces.

The standard error I get in the delayed_job mysql table is:

{undefined method `name' for nil:NilClass...

where 'name' is the first argument in the mailer's view (@contact.name). This works fine if I take delayed_job out again.

If I remove all references to @contact in the view, I get

{A sender (Return-Path, Sender or From) required to send a message

In short, it doesn't seem to be understanding any arguments at all.

All relevant code below - if anyone has any suggestions for this it would be very appreciated

CONTROLLER

  def sendmail
    @contact = Contact.new(params[:contact])
    if @contact.save
      ContactMailer.delay.contact_mail(@contact)
      flash[:notice] = 'Your message has been successfully sent'
      redirect_to root_path
    else
      render :action => 'index'
    end
  end

MAILER:

class ContactMailer < ActionMailer::Base
  default :from => "my@email.address"  

  def contact_mail(contact)
    @contact = contact
    mail(:to => 'my@email.address', :subject => 'Contact Form Query', :from => 'my@email.address', :content_type => 'text/plain')
  end
  handle_asynchronously :contact_mail, :run_at => Proc.new { 2.seconds.from_now }
end

MAILER VIEW:

You have received a new query:
-----------------------------------

<%= @contact.name %>

<%= @contact.business %>

<%= @contact.phone %>

-----------------------
<%= @contact.message %>
-----------------------

INITIALIZER:

Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.max_run_time = 5.weeks

And finally, the full error message:

    {undefined method `name' for nil:NilClass

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0/lib/active_support/whiny_nil.rb:48:in `method_missing'

/Users/john/Websites/Rails/InDevelopment/connectted/app/views/contact_mailer/contact_mail.html.erb:4:in `_app_views_contact_mailer_contact_mail_html_erb___3386534441642202773_2166008980__4301703149293725172'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/action_view/template.rb:135:in `block in render'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0/lib/active_support/notifications.rb:54:in `instrument'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/action_view/template.rb:127:in `render'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/action_view/render/rendering.rb:59:in `block in _render_template'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0/lib/active_support/notifications.rb:52:in `block in instrument'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.0/lib/active_support/notifications/instrumenter.rb:21:in `instrument'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/activesu开发者_如何学运维pport-3.0.0/lib/active_support/notifications.rb:52:in `instrument'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/action_view/render/rendering.rb:56:in `_render_template'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/action_view/render/rendering.rb:26:in `render'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/abstract_controller/rendering.rb:114:in `_render_template'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/abstract_controller/rendering.rb:108:in `render_to_body'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/abstract_controller/rendering.rb:101:in `render_to_string'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/abstract_controller/rendering.rb:92:in `render'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/deprecated_api.rb:111:in `render'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/old_api.rb:210:in `block in create_parts'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/old_api.rb:208:in `each'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/old_api.rb:208:in `create_parts'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/deprecated_api.rb:143:in `create_parts'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/old_api.rb:77:in `process'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/base.rb:446:in `process'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/base.rb:441:in `initialize'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/base.rb:425:in `new'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/actionmailer-3.0.0/lib/action_mailer/base.rb:425:in `method_missing'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/performable_mailer.rb:6:in `perform'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/backend/base.rb:83:in `invoke_job'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:119:in `block (2 levels) in run'

/Users/john/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/timeout.rb:57:in `timeout'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed
/worker.rb:119:in `block in run'

/Users/john/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/benchmark.rb:309:in `realtime'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:118:in `run'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:176:in `reserve_and_run_one_job'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:103:in `block in work_off'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:102:in `times'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:102:in `work_off'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:77:in `block (2 levels) in start'

/Users/john/.rvm/rubies/ruby-1.9.2-p0/lib/ruby/1.9.1/benchmark.rb:309:in `realtime'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:76:in `block in start'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:73:in `loop'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/worker.rb:73:in `start'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/command.rb:100:in `run'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/command.rb:79:in `block in run_process'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/application.rb:250:in `call'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/application.rb:250:in `block in start_proc'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/daemonize.rb:199:in `call'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/daemonize.rb:199:in `call_as_daemon'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/application.rb:254:in `start_proc'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/application.rb:294:in `start'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/controller.rb:70:in `run'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons.rb:193:in `block in run_proc'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/cmdline.rb:112:in `call'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons/cmdline.rb:112:in `catch_exceptions'

/Users/john/.rvm/gems/ruby-1.9.2-p0/gems/daemons-1.1.0/lib/daemons.rb:192:in `run_proc'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/command.rb:78:in `run_process'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/command.rb:72:in `block in daemonize'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/command.rb:70:in `times'

/Users/john/.rvm/gems/ruby-1.9.2-p0/bundler/gems/delayed_job-c933ffcd776a/lib/delayed/command.rb:70:in `daemonize'
script/delayed_job:5:in `<main>' |


The issue is with the code in your mailer taking the object instead of the objects id:

def contact_mail(contact)
    @contact = contact
    mail(:to => 'my@email.address', :subject => 'Contact Form Query', :from => 'my@email.address', :content_type => 'text/plain')
end

You should change that to this:

def contact_mail(contact_id)
    @contact = Contact.find(contact_id)
    mail(:to => 'my@email.address', :subject => 'Contact Form Query', :from => 'my@email.address', :content_type => 'text/plain')
end

Never pass the actual objects to your mailer. Simply pass the id's and retrieve them upon processing.


I had this same problem, and fixed it by moving all the attributes into instance variables. So, in the view:

<%= @contact.name %>
<%= @contact.business %>
<%= @contact.phone %>

becomes:

<%= @name %>
<%= @business %>
<%= @phone %>

and I just looked up the instance variables in the mailer method. So, in the mailer:

def contact_mail(contact)
    @contact = contact
    mail(:to => 'my@email.address', :subject => 'Contact Form Query', :from => 'my@email.address', :content_type => 'text/plain')
end

becomes:

def contact_mail(contact)
    @name = contact.name
    @business = contact.business
    @phone = contact.phone
    mail(:to => 'my@email.address', :subject => 'Contact Form Query', :from => 'my@email.address', :content_type => 'text/plain')
end


Why is it not working? Not sure, I imagine it has to do with some ActionMailer voodoo.

How to get it working? Abstract out the delayed job pieces into another class. Have the method that is delayed do nothing more than send them email; meaning that the rendering of the email is done in real time, but the sending of it is delayed. This should get around your problem and accomplish the asynchronous sending of emails.


Hey this might be far off, but you're not sending any params to your MAILER. Here's a copy of my referred_email.rb I keep in my lib/ dir. I call it with delayed_job:

#my controller
Delayed::Job.enqueue ReferredEmail.new(params[:subject], params[:editor1])

#Reffered_Email.rb

class ReferredEmail < Struct.new(:subject, :editor1)
  def perform
    (CardReferral.all.map(&:email) - CardSignup.all.map(&:email)).each do |cf|
      @cf = CardReferral.find_by_email(cf)
      Notifier.deliver_referred_magic_email(User.find(@cf.user_id), @cf.email, @cf.name, @cf.message, subject, editor1)
    end
  end
end


It seems like you are using both:

  ContactMailer.delay.contact_mail(@contact)

and

  handle_asynchronously :contact_mail, :run_at => Proc.new { 2.seconds.from_now }

which you should only do one or the other. Try removing the handle_asynchronously and see if that fixes the problem.

0

精彩评论

暂无评论...
验证码 换一张
取 消