views:

100

answers:

2

Hi,

I am trying to use delayed_job on heroku and I get the following error:

Cannot enqueue items which do not respond to perform

I am using the plugin http://github.com/pedro/delayed_job

I am using the following cron rake task (cron.rake):

task :cron => :environment do
require 'heroku'    
    puts "starting the cron job at #{Date.today}"

    heroku = Heroku::Client.new(ENV['HEROKU_USER'], ENV['HEROKU_PASS'])
    heroku.set_workers(ENV['HEROKU_APP'], 1)

    Contact.all.each do |contact|
      email = contact.email_today #email_today is a contact method returning email object if <= today

      unless contact.email_today == "none"
        puts contact.first_name
        puts email.days
        puts contact.date_entered
        puts email.substituted_subject(contact,contact.colleagues)

        # create the Contact Email object that gets created and sent

        contact_email = ContactEmail.new
        contact_email.contact_id = contact.id
        contact_email.email_id = email.id

        contact_email.subject = email.substituted_subject(contact,contact.colleagues)
        contact_email.date_sent = Date.today
        contact_email.date_created = Date.today

        contact_email.body = email.substituted_message(contact, contact.colleagues)

        contact_email.status = "sent" 

        Delayed::Job.enqueue OutboundMailer.deliver_campaign_email(contact,contact_email)

        contact_email.save #now save the record
        puts "save contact_email:"
        puts contact_email.inspect

      end #end unless

    end #end do

    heroku.set_workers(ENV['HEROKU_APP'], 0)
    puts "set heroku workers to 0"

end

This is the mailer I am using:

class OutboundMailer < Postage::Mailer 

  def campaign_email(contact,email)
    subject    email.subject
    recipients contact.email
    from       'Me <[email protected]>'
    sent_on    Date.today

    body       :email => email
  end

Question: Why am I getting the error and what can I do to solve it?

+2  A: 

A job is usually a ruby object with a method "perform", thus enqueuing a mailer deliver will not work, you will have to create a job object like this below,

 class SomeMailJob < Struct.new(:contact, :contact_email) 
   def perform
     OutboundMailer.deliver_campaign_email(contact,contact_email)
   end
 end

Create a file some_mail_job.rb and place this in /lib

and

in above code, replace the enqueue statement with

Delayed::Job.enqueue SomeMailJob.new(contact,contact_email)

Rishav Rastogi
also, read the documentation http://github.com/pedro/delayed_job . its all there
Rishav Rastogi
Hi, will do -- I read it but someone else on SO said to do it as described so wasn't sure....your approach is alot clearer, thanks.
Angela
+1  A: 

If you don't need to pass other options to Delayed::Job.enqueue, then this is a simpler solution:

OutboundMailer.delay.deliver_campaign_email(contact,contact_email)

FYI delay used to be called send_later, depending on your delayed_job branch and version.

tfe
Does thsi also work on heroku with workers just as is?
Angela
So I use this as the cron with using delayed:job enque altogether?
Angela
This is an alternative (shorter) syntax on creating your own SomeMailJob and sending an instance of it to `Delayed::Job.enqueue`. That is all. In order to use it on Heroku, you need to install delayed_job into your app as a gem or plugin, but that should be all.
tfe