2

I've a ruby script that has been implemented as an independent functionality. Now I would like to execute this script in my rails environament, with the added difficulty of executing it as a background job, because it needs a great amount of time processing.

After adding the delayed_job gem, I've tryied calling the following sentence:

delay.system("ruby my_script.rb")

And this is the error I get:

Completed 500 Internal Server Error in 95ms
TypeError (can't dump anonymous module: #<Module:0x007f8a9ce14dc0>):
   app/controllers/components_controller.rb:49:in `create'
user1573607
  • 522
  • 9
  • 23

2 Answers2

4

Calling the self.delay method from your controller won't work, because DJ will try to serialize your controller into the Job. You'd better create a class to handle your task then flag its method as asynchronous :

class AsyncTask
  def run
    system('ruby my_script.rb')
  end
  handle_asynchronously :run
end

In your controller :

def create
    ...
    AsyncTask.new.run
    ...
end

See the second example in the "Queing Jobs" section of the readme.

Jef
  • 5,424
  • 26
  • 28
  • Ok, and how can I debug it? Puts or logger are not being effective inside the run method. – user1573607 Nov 13 '12 at 11:35
  • Did you try with `Delayed::Worker.logger` ? – Jef Nov 13 '12 at 11:43
  • `Delayed::Worker.logger "test log"` should write the string in the console, isn't it? It's not working. By the way, I've implemented the async task as Erez post, the method is the same? – user1573607 Nov 13 '12 at 11:53
  • Did you check the log/test.log file ? – Jef Nov 13 '12 at 11:56
  • There isn't the file. Should I write `Delayed::Worker.logger = Rails.logger` or using it as logger directly? – user1573607 Nov 13 '12 at 12:04
  • DelayedJob uses the Rails logger by default (https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/worker.rb). Did you have a look at this post http://stackoverflow.com/questions/9507765/delayed-job-not-logging ? – Jef Nov 13 '12 at 12:52
  • Rails log files can be found in the log directory, each one corresponding to an environment : test.log, development.log and so on. – Jef Nov 13 '12 at 12:53
  • Fixed. I'm really sorry, I didn't realised that to make delayed_job run, `rake jobs:work` was needed. Thanks, Jef. – user1573607 Nov 14 '12 at 10:32
0

Like Jef stated the best solution is to create a custom job. The problem with Jef's answer is that its syntax (as far as I know) is not correct and that's his job handles a single system command while the following will allow you more customization:

# lib/system_command_job.rb
class SystemCommandJob < Struct.new(:cmd)
  def perform
    system(cmd)
  end
end

Note the cmd argument for the Struct initializer. It allows you to pass arguments to your job so the code would look like:

Delayed::Job.enqueue(SystemCommandJob.new("ruby my_script.rb"))
Erez Rabih
  • 15,562
  • 3
  • 47
  • 64
  • Erez, (as far as I can tell ;)) `handle_asynchronously` is correct use whenever "a method should always be run in the background" (quoted from DJ README) I tried to answer with concise code and close to the examples provided by the documentation – Jef Nov 13 '12 at 11:30
  • Erez, to debug Delayed::Worker.logger is not working, any ideas? – user1573607 Nov 13 '12 at 11:54