Nicolas Raoul
Nicolas Raoul

Reputation: 60193

delayed_job: NoMethodError

Here is my tiny Rails3 controller:

class HomeController < ApplicationController
  def index
    HomeController.delay.do_stuff
  end
  def self.do_stuff
    puts "Hello"
  end
end

Upon accessing index, the job gets correctly inserted in database:

--- !ruby/struct:Delayed::PerformableMethod 
object: !ruby/object:Class HomeController
method_name: :do_stuff

PROBLEM: When executing bundle exec rake jobs:work, I get:

Class#do_stuff failed with NoMethodError:
    undefined method `do_stuff' for #<Class:0x0000000465f910>

Despite the fact that HomeController.do_stuff works perfectly. Any idea?

Upvotes: 1

Views: 2491

Answers (3)

Petr
Petr

Reputation: 3249

See https://github.com/collectiveidea/delayed_job/wiki/Common-problems#wiki-undefined_method_xxx_for_class in documentation.

It seems that you should have

..object: !ruby/class HomeController method_name ...

in the database, but you have

..object: !ruby/object:Class HomeController method_name ...

instead. Which is bad.

Even delayed_job author don't know the reason. It somehow depends on the webserver you run in on. Try the wiki's recommendation.

Upvotes: 2

Peru
Peru

Reputation: 383

I my case the problem was mainly because I was passing Hash as a parameter to object that was passed to delayed_job queue. But after 25 trails I have come to conclusion that delayed_job accepts objects only with integer as parameter. Hence I stored all the parameters in the database and then passed that record id as parameter to delayed_job and inside the perform function we can access all the parameters with that record id and delete that record after fetching that data.

Delayed::Job.enqueue LeadsJob.new(params[:customer]) # this job will be queued but will never run, this is because of the way Delayed_job serializes and De-serializes the objects.

instead do something like this

@customer = Customer.create(params[:customer])
Delayed::Job.enqueue LeadsJob.new(@customer.id)

If the customer details was just to pass the parameters then delete that record inside the function.

Please ping me if you need more details on the same.

The problem might be also because of the YAML parser that Delayed_Job uses but I haven't tried out that option that is mentioned by @Stefan Pettersson

Upvotes: 0

Stefan Pettersson
Stefan Pettersson

Reputation: 453

I had the same problem.

I found several discussions stating that different yaml parsers were used by when the job was put in the queue by the web application and when it was executed later.

Some suggest the psych parser should be used. Some suggests syck. First I tried psych but ended up with incompability issues with other gems. So I picked syck.

I wasn't able to sort out which configuration files that are used by the web server and the queue. After a lot of experimentation I ended up with the following configurations (all of them in the top of the file):

#application.rb
require File.expand_path('../boot', __FILE__)

require 'rails/all'
require 'yaml'
YAML::ENGINE.yamler= 'syck'
# ...

and

#environment.rb
require 'yaml'
YAML::ENGINE.yamler= 'syck'
# ...

and

#boot.rb
require 'yaml' 
YAML::ENGINE.yamler= 'syck' 
require 'rubygems'
# ...

I'm using Ruby 1.9.3, Rails 3.2.8, Webrick, delayed_job 3.0.3

Upvotes: 0

Related Questions