Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Ajax - render multiple responses in one action

I have an ajax request in my rails app that returns a variable from my controller action. Inside the controller action I have a loop that can take some time to get through.

Controller

def myAction
  $j = 1 
  until $j > list_size do
    array <<  {  :foo => $j }   
    $j +=1;
  end  
  @myvariable = array.to_json
end

myAction.js.erb

 var myVariable = JSON.parse("<%= escape_javascript(raw @myvariable) %>");
 for (var k = 0; k < myVariable.length; k++) {
   $("#myDiv").append(myVariable[k].foo);
 }

I want to be able to render the results at each stage of the loop to the js.erb partial instead of waiting for the loop to finish. Is this possible without breaking the loop and ending the action prematurely before the loop finishes? Maybe something like this (pseudo code that is wrong):

Controller

def myAction
  $j = 1 
  until $j > list_size do
    array <<  {  :foo => $j }   
    render array.to_json
    $j +=1;
  end  
end

myAction.js.erb

 var myVariable = JSON.parse("<%= escape_javascript(raw @myvariable) %>");
 $("#myDiv").append(myVariable.foo);
like image 647
diasks2 Avatar asked Jan 21 '14 11:01

diasks2


1 Answers

render stream: true will lazily load the queries and allow them to run after the assets and layout have been rendered. Streaming only works with templates and not any other forms (such as json or xml).

So, you are out of luck & you will have to use ActionController::Live which is available in Rail 4 & above. Live is a special module included in ActionController class. It enables Rails to open and close a stream explicitly. Here is the pseudo code adaptated to be more ruby-like & avoiding global variables:

class MyController < ActionController::Base
  include ActionController::Live
  def action
    (1..list_size).each do |list_item|
      response.stream.write("{  "foo": #{list_item} }")
    end
  ensure
     response.stream.close
  end  
end

Above code will loop from 1 to list_size and output each list_item immediately.

to you use this, you should use Server-Sent Events. Normally, the web page would have to ask if any updates were available. With server-sent events, the updates come automatically.

Please use the following Resources to learn more aboue Streaming, SSE & Event Source:

like image 99
CuriousMind Avatar answered Sep 27 '22 21:09

CuriousMind