ruby-on-railsruby-on-rails-3delayed-job

Delay a user defined helper method with delayed_job


So i have many database operations that i put into my helpers that i want to do in the background. As an example, I define a record_activity method in my Users helper. When a Post gets created I want to record this activity ie in the create method in the Posts controller:

 def create
     #operations to save the post
     record_activity(user, post)
 end

For performance reasons, I want to delay this record_activity and others, and run them with workers on the back-end. I use delayed_job for delaying mailers and it works excellently. In rails console, method.delay works great ie I could in rails console do:

 record_activity.delay

However, the same .delay doesn't work when written in a controller ie the following still runs live, not delayed:

 def create
     #operations to save the post
     record_activity(user, post).delay
 end

Why is this? I'm using Rails 3.0.9 in one app and Rails 3.1.3 in another, plus I have delayed_job version 2.1.4.

Can anyone suggest how to make this work?

EDIT *

I think the answer provided by mu_is_too_short is the right path. It creates a delayed job, only it doesn't execute the record_activity method properly. When the delayed_job worker starts, it executes the delayed_job and has no errors, and deletes the record as if it worked. But no activity gets recorded. To give some context, here is the call and the method i am troubleshooting now:

self.delay.record_activity(user, @comment)

ANd the method:

def record_activity(current_user, act)
   activity = Activity.new
   activity.user_id = current_user.id
   activity.act_id = act.id
   activity.act_type = act.class.name
   activity.created_at = act.created_at
   activity.save
end 

I then thought that maybe I couldn't pass user variables through, in this case, so I tried to just pass integer values and so on. I restarted the delayed_job workers and tried these methods, to no avail:

    self.delay.record_activity(user.id, @comment.id, @comment.class.name, @comment.created_at)

And the altered method:

   def record_activity(current_user_id, act_id, act_type, act_created_at)
     activity = Activity.new
     activity.user_id = current_user_id
     activity.act_id = act_id
     activity.act_type = act_type
     activity.created_at = act_created_at
     activity.save
   end

Solution

  • I don't think record_activity.delay in the console is working the way you think it is. That will execute record_activity before delay has a chance to do anything.

    The delay call has to go first, then you call your delayed method on what delay returns:

    def create
      self.delay.record_activity(user, post)
    end
    

    The delay call will return an object that intercepts all method calls (probably through method_missing), YAMLizes them, and adds the YAML to its delayed job queue table in the database. So, just saying record_activity.delay doesn't do anything useful, it just executes record_activity, creates the delayed-job interceptor object, and throws away what delay created.