Take the 2-minute tour ×

This is my first post here but I have gotten some great info from this site already. So I thought someone may be able to help.

In my view I have a form that once submitted, the controller passes the job off to navvy and it really works well. The problem is I would like to have another partial on the same page as the form update with the new info once navvy is done working. So in my controller I have:

Navvy::Job.enqueue( GetZip, :get_zip,  @series, :job_options => {:priority => 8})

And then in my navvy block which is located in config/initializers/navvy.rb I have:

class GetZip
def self.get_zip(params)
  fetch = Fetch.new
# What to put here to update partial #

Which works as expected. I am just not sure how I can have the partial in my view updated once the navvy job is completed. Any suggestions would be greatly appreciated.

share|improve this question

2 Answers 2

up vote 3 down vote accepted

The problem here is that once you've fired up a background process you're no longer tied into that user's request (which is obviously the point of the background process).

So your background job is not aware of what the user is doing in the meantime. For example they could navigate to another page, or even leave your website.

You could get your background job to create a record in a database that indicates it has started processing and update this status when it has finished processing. That way when the user next refreshes the page you can check the status of that record and the partial can be updated accordingly.

If you want the page to auto-update you could keep polling the status of that record with ajax requests. On the initial submission of the form you could start the polling rather than have it running all the time.

share|improve this answer
I suppose this is what I will have to do. Although I was thinking there might be another way. I did neglect to mention that this is a one page app meant to be run only on a local network. –  fxe74 Apr 18 '11 at 1:42

Here's what I'm using. This is where the Job is called:

Setting::progress = "Starting..."
Navvy::Job.enqueue(EmailWorker, :async_email, stuff)

Settings is super simple:

class Setting < ActiveRecord::Base
  def Setting::progress=(value)
    setn = Setting.find_or_initialize_by_name("email_status")
    setn.value = value

and the navvy job EmailWorker is:

class EmailWorker
  def self.async_email(options)
    # send one at a time
    total = options[:list].length
    errors = []
    options[:list].each_with_index do |email_addr, n|
        Setting::progress = "#{n+1}/#{total}: #{email_addr}"
        Postoffice.one_notice(email_addr, options).deliver
      rescue Exception => e
        Setting::progress = "#{email_addr} #{e.message}"
        errors << "<span class='red'>#{email_addr}</span> #{e.message}"
      # get stack level too deep errors at random when this is removed. I don't get it.
      sleep 0.05 
    Setting::progress = "DONE sending #{total} with #{errors.length} errors<br/>#{errors.join("<br/>")}"
    "Done"  # just for display in Navvy console output

Then the triggering page has this:

# had to add this back as rails 3 took it away
  def periodically_call_remote(options = {})
    frequency = options[:frequency] || 10 # every ten seconds by default
    code = "new PeriodicalExecuter(function() {#{remote_function(options)}}, #{frequency})"
<script type="text/javascript">
  check_var = true;
<%= periodically_call_remote(
      :condition => "check_var == true",
      :url => { :controller => "application", 
      :action => "update" }, 
      :frequency => '3') -%>
<div id="progress">
  <p>Monitoring progress of emails</p>

And heres the method that's called repeatedly:

def update
  raise "not for direct" if (!request.xhr?)
  @progress = Setting::progress
  @again = !(/^DONE/ =~ @progress)
  render :action => "update"

Which trigers an in-place update via update.rjs

page.assign('check_var', @again)
page.replace_html "progress", :partial => "info", :locals => { :info => @progress } 
page.visual_effect :highlight, 'progress', :startcolor => "#3333ff",  :restorecolor => '#ffffff', :duration => 0.5

One word of warning about Navvy - since it runs as a background task until killed, it will stay executing your old app when you cap deploy. You must kill navvy in old "current" and move to new "current".

share|improve this answer
Please can you explain me where locate file update.rjs? In assets/javascripts? –  Nikolay Moskvin Mar 2 '12 at 8:40

Your Answer


