3

I have a rails app that imports all your Facebook contacts. This takes some time. I would like to be able to show a "please wait" page while the importing keeps happening in the back.

It seems that I cannot put render and redirect_to on the same action in the controller. How can I do this?

if @not_first_time
    Authentication.delay.update_contact_list(current_user)
else
    render 'some page telling the user to wait'
    Authentication.import_contact_list(current_user)
end
redirect_to :root_path, :notice => 'Succesfully logged in'

If it is the users first time in the site, i want to render a "please wait page", start importing, and once its done redirect to the root path, where a lot of processing with this data happens

If it is not the first time, then put the contact update in the background (using the delayed_jobs gem) and go straight to the home page

I'm using the fb_graph gem to import the contacts. Here's the method

def self.import_contact_list(user)
  user.facebook.friends.each do |contact|
  contact_hash = { 'provider' => 'facebook', 'uid' => contact.identifier, 'name' => contact.name, 'image' => contact.picture(size='large') }
  unless new_contact = Authentication.find_from_hash(contact_hash)
    ##create the new contact
    new_contact = Authentication.create_contact_from_hash(contact_hash)
  end
  unless relationship = Relationship.find_from_hash(user, new_contact)
    #create the relationship if it is inexistent
    relationship = Relationship.create_from_hash(user, new_contact)
  end
end

end

Edit

I added the solution suggested below, it works!

Here's is my 'wait while we import contacts' view from the action "wait"

<script>
jQuery(document).ready(function() {
  $.get( "/import_contacts", function(data) {
    window.location.replace("/")
  });
});
</script>

<% title 'importing your contacts' %>

<h1>Please wait while we import your contacts</h1>
<%= image_tag('images/saving.gif') %>

Thanks!

wachichornia
  • 1,178
  • 14
  • 31
  • have you thought about using ajax? maybe this would result in a much easier and more fluid soltion. – alex Apr 07 '12 at 10:47
  • 1
    AJAX is the solution for you. Have a look on this http://api.jquery.com/jQuery.get/ if you are using jQuery. The AJAX get in jQuery provides a callback function that will be executed when the request returns (in your case the contacts are imported). After the request is returned you can view whatever message you want (in your case "Succesfully logged in") – mohamagdy Apr 07 '12 at 11:02
  • I did think of using Ajax. But i'm importing using the [fb_graph gem](https://github.com/nov/fb_graph), and I would not like to break into the gems code... see edited answer above – wachichornia Apr 07 '12 at 11:11
  • 2
    Build a Page where you render "Some page telling user to wait" do a AJAX call to the controller action which imports the contacts from facebook and do the render in this action AFTER the import has finished and you should be fine! When the AJAX response is received replace the waiting message with the result from the server! – alex Apr 07 '12 at 11:19

1 Answers1

1

A single request receives a single response - you can't render content and redirect.

If I were you I would always do the lengthy process in delayed job - tying up passenger/unicorn instances is never a great idea. Render a 'please wait page' that refreshes periodically to check whether the delayed job has completed (if you stash the id of the delayed job you can test whether it is still in the db. When te job completes it will be deleted). When the job is complete, redirect to the results page. You could also do the periodic checking bit via ajax.

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
  • that was my initial intention, but it turns out that delayed_job never starts processing the data while the server is busy, and the server is always busy. So the job would take hours (if not never) to actually be executed (tested). Is there a way to change this behavior? – wachichornia Apr 07 '12 at 13:07
  • That doesn't sound like something I've ever seen delayed job do - it doesn't have any knowledge of what the application instances are doing – Frederick Cheung Apr 07 '12 at 13:33