Reputation: 351
I need to generate a big report file in background. Here is a simple view to create a OrderReport
object.
<%= simple_form_for order_report, remote: true do |f| %>
<%= f.input :start_date, as: :date, html5: true %>
<%= f.input :end_date, as: :date, html5: true %>
<%= f.submit "Generate report", id: "test" %>
<% end %>
And that what is going on in the controller:
def create
order_report = OrderReport.new(order_report_params)
order_report.user = current_user
order_report.save
OrderReportJob.new(order_report).delay.perform
render nothing: true
end
After user click a submit button this action creates a background process to generate report. I wrote endpoint to check the status of this background job. This JS is a onclick
function to Submit buttom by id #test
$.ajax({
url: report_url,
success: function(report) {
if(report.status === 'progress') {
$("#spin").show();
$interval = setInterval(checkStatus, 3000);
}
}
});
This is a part of the JS script. It works good, but the final step to send the ID of created OrderReport
to this js file. As you can see in the JS script I have a variable report_url
- it's already hardcoded and looks like
var report_url = '/order_reports/1'
So the main idea is to catch the ID of created OrderReport
, if it's possible, and use it in the JS script. How can I pass it correctly?
Update:
order_report.js
$(function () {
$('#test').click(function() {
var report_url = '/order_reports/39'
$.ajax({
url: report_url,
success: function(report) {
if(report.status === 'progress') {
$interval = setInterval(checkStatus, 3000);
}
}
});
function checkStatus() {
$.ajax({
url: report_url,
success: function(report) {
if(report.status === 'done') {
clearInterval($interval)
}
}
});
}
});
});
Upvotes: 0
Views: 71
Reputation: 101976
A more RESTful solution is to use meaningful response codes to tell the client what happened with the request:
def create
order_report = OrderReport.new(order_report_params)
order_report.user = current_user
respond_to do |format|
if order_report.save
OrderReportJob.new(order_report).delay.perform
format.json { head :created, location: order_report }
else
format.json { head :unprocessable_entity }
end
end
end
head :created, location: order_report
returns a 201 - Created
response with a location
header that contains a url to the created resource.
This lets you listen for the Rails UJS ajax:success
and ajax:error
events:
<%= simple_form_for order_report, remote: true, html: { class: 'order_report_form', 'data-type' => 'json'} do |f| %>
<%= f.input :start_date, as: :date, html5: true %>
<%= f.input :end_date, as: :date, html5: true %>
<%= f.submit "Generate report", id: "test" %>
<% end %>
$(document).on('ajax:success', '.order_report_form', function(e, data, status, xhr){
function checkStatus(url) {
return $.getJSON(url).then(function(data) {
// some logic here to test if we have desired result
if (!desiredResult) {
// never use setInterval with ajax as it does not care
// if the previous request is done.
// instead use setTimeout with recursion
setTimeout(1000, function(){ checkStatus(url) });
} else {
// do something awesome
}
}
}
checkStatus(xhr.getResponseHeader('location'));
});
$(document).on('ajax:error', '.order_report_form', function(){
alert("Oops");
});
Upvotes: 1