Reputation: 1107
I'm trying to create multiple objects called "baseRules" in jQuery by calling post requests to my Rails controllers. Nested inside of this creation of objects are a subset of rules, called "matchTypes", that belong to the main rules. I need to assign a foreign_id to this subset for it to work correctly though. Is there any way to get the ID of the main rules object as soon as it's created in jQuery?
Here is my Javascript code:
for (var i = 0; i < baseRules.length; i++) {
$.post('/rule_types', {
name: baseRules[i][0],
matchFlag: baseRules[i][1]
}, function () {
if (baseRules[i][1]) {
for (var k = 0; k < baseRules[i][2].length; k++) {
$.post('/match_types', {
name: matchType[i][2][k],
rule_type_id: ? ? ? ?
}, function () {
});
}
}
});
}
And here are my controller methods:
class RuleTypesController < ApplicationController
def create
@ruleType = RuleType.new
@ruleType.name = params[:name]
@ruleType.matchFlag = params[:matchFlag]
respond_to do |format|
if @ruleType.save
format.html{redirect_to root_path}
format.js{}
else
format.html{}
format.js{}
end
end
end
end
class MatchTypesController < ApplicationController
def create
@matchType = MatchType.new
@matchType.name = params[:name]
matchType.rule_types_id = params[:rule_type_id]
respond_to do |format|
if @ruleType.save
format.html{redirect_to root_path}
format.js{}
else
format.html{}
format.js{}
end
end
end
end
Upvotes: 1
Views: 516
Reputation: 76774
In respect to your question (the extra "frills" can be addressed after), in order to receive the id
of a newly created object, you should be able to capture it with the ajax:success request.
Ajax
Your flow is slightly complicated (Ajax is asynchronous), meaning that if you want to use the data you receive, you may have to use an ajax callback (not as complicated as it sounds)
If you create a new record, Rails will ALWAYS fire back a response. Inside this response, you can access the id
attribute of the newly created record, allowing you to access the new ID for your object:
for (var i = 0; i < baseRules.length; i++) {
$.post('/rule_types', {
name: baseRules[i][0],
matchFlag: baseRules[i][2]
}, function (data) {
var returnedData = JSON.parse(data);
if (baseRules[i][3]) {
for (var k = 0; k < baseRules[i][2].length; k++) {
$.post('/match_types', {
name: matchType[i][2][k],
rule_type_id: returnedData.id //Calls the original "ID" of the returned post
}, function () {
});
}
}
}, dataType: "json");
}
This will give you the ability to determine JSON responses in your controller:
#app/controllers/rules_types_controller.rb
class RuleTypesController < ApplicationController
respond_to :js, :json, :html
def create
@ruleType = RuleType.new
@ruleType.name = params[:name]
@ruleType.matchFlag = params[:matchFlag]
@ruleType.save
respond_with @ruleType
end
end
end
Response
Although I think you'll make progress with what I've posted, you'll want to look at how you're using the $.post
function. Although it should work as you have it now, you need to appreciate that if you try and use ajax functionality synchronously
, it will likely freeze your UI whilst the request completes
The way to solve this is to use an Ajax callback. We've done this before:
function fetch(link, data, response, type = "script") {
$.post(link, data, response(data), dataType: type);
}
for (var i = 0; i < baseRules.length; i++) {
fetch('/rule_types', {
name: baseRules[i][0],
matchFlag: baseRules[i][2]
}, function (data) {
var returnedData = JSON.parse(data);
if (baseRules[i][3]) {
for (var k = 0; k < baseRules[i][2].length; k++) {
fetch('/match_types', {
name: matchType[i][2][k],
rule_type_id: returnedData.id //Calls the original "ID" of the returned post
});
}
}
}, "json");
}
This should make it so that your ajax calls are truly asynchronous - updating only when they have the data returned from the server. I can re-factor this if you'd prefer
Upvotes: 1