Cannot receive Rails response with Ajax - javascript

When I post from phonegap (with ajax, in javascript) something to my rails server, the post succeeds, but I have no response from my server, so finally it fails. I don't understand why I cannot get the response ..
For example, here is my sign up script (javascript with ajax):
$('#sign-up-button').click(function(e) {
var str = $("#signUpForm").serialize();
$(".error").remove();
e.preventDefault();
$.ajax({url: "http://localhost:3000/api/users.json",
type: "POST",
data: str,
success: function(result, status) {
alert('success');
$.mobile.changePage( "welcome.html", { transition: "slide"} );
},
error: function(result) {
alert('error');
}
});
});
and my code on Ruby on rails side:
# POST /users
# POST /users.json
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
In firebug, I have : the message 201 Created, the user is created (I can check it), but I have no response, so the message alert('error') appears ...
Thanks a lot for your advices!

If you are expecting an empty response such as a 201, you need to specify dataType: 'text' in your $.ajax options. What's happening right now is that jQuery is attempting to parse the response as JSON, and failing as there is no response to parse.

I've just stopped to try making it working with Firefox, and launched it in X-code.
It worked.
I was wondering if I needed to work on a server to obtain a response from a post, somebody knows if X code creates a server?

Related

Is there a way to render a js.erb after a fetch call?

In my Rails app, I want to render a js.erb partial after a fetch call and for some reasons I do not understand it does not work. If you can help me, it would be great.
In a view, an event trigger this function that basically do a fetch request:
function updateState(id, state){
const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes
.content.value;
fetch(window.location.origin + "/update_state", {
method: "POST",
headers: {
'Accept': "JS",
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({'id': id, 'state': state}),
credentials: "same-origin"
})
}
Then in my controller:
def update_state
#model = Model.find(params[:id])
authorize #model
#model.update(state: params[:state])
respond_to do |format|
format.html { redirect_to xxx }
format.js
end
end
In my js.erb files:
console.log('hello');
However, in that case, I get an error from the server:
ActionController::UnknownFormat
at the line 'respond_to do |format|
I have the feeling that the server do not understand the header of the fetch:
'Accept': "JS"
When I look at the logs of the server:
Started POST "/update_state" for 127.0.0.1 at 2019-04-04 11:22:49 +0200
Processing by ModelsController#update_state as JS
But I think that Rails does not recognize it. How do I do?
I tried also this in the controller:
def update_state
#model = Model.find(params[:id])
authorize #model
#model.update(state: params[:state])
render 'update_state.js', layout: false
end
Which does not fire errors. I received in the client side the js.erb. However, it is not executed (console.log does not execute).
Do you have any idea? Thank a lot for your help.
I manage the other way around. I never succeded with js.erb.
So I use a fetch call with a response in text:
function updateState(id, state){
const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes
.content.value;
fetch(window.location.origin + "/update_state", {
method: "POST",
headers: {
'Accept': "JS",
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({'id': id, 'state': state}),
credentials: "same-origin"
}).then(response => response.text())
.then(data => {
div.inserAdjacentHTML('XXX', data);
});
}
Then in the controller/action:
def update_state
#model = Model.find(params[:id])
authorize #model
#model.update(state: params[:state])
render 'update_state.js', layout: false, content_type: "text/plain"
end
That way, it works. Hope it helps.
Edit : look at the edit for a fully working solution on triggering manually a .js.erb file.
Had the same issue and there are actually two problems here. Your are right, your headers are not. These headers to trigger the .js.erb worked for me and seems pretty right :
'dataType': 'json',
'contentType': 'application/json; charset=utf-8',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': - your CSRF method to get the token -
But secondly to trigger the js response, your respond_to block :
respond_to do |format|
format.html { redirect_to xxx }
format.js
end
Has to have the format.js first. As rails has a response for the HTML it will respond with HTML first and seems to not even look for the next format block.
respond_to do |format|
format.js
format.html { redirect_to xxx }
end
Hope it helps :-)
Edit 13/11/2018
Hey, long time no see ! The same issue happened to me again and my own previous reply wasn't solving the issue. Like you, the .js.erb file was rendered but nothing happened and the console.log was not displayed. So I created a link_to with remote: true that triggered my .js.erb file and compared the requests. Everything was the same except one thing : the type of the request. One was a fetch, the other was an xhr. It appears that the .js.erb files are triggered only by the xhr requests. So the solution is to build an old xhr request instead of a fetch, like this :
const url = 'your_custom_path' // Build the url to fetch
const csrf = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
let xhr = new XMLHttpRequest();
// Will be a GET request here
xhr.open('GET', url, false);
​
// Setting the headers
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.setRequestHeader('X-CSRF-Token', csrf);
xhr.setRequestHeader('dataType', 'script');
​
// What to do with the response
xhr.onload = function() {
let responseObj = xhr.response
eval(responseObj) // You need to eval() manually the response for it to be executed
}
​
// Sending the request
xhr.send()
Hope it helps, even some months later! ;)
I ran into this issue in Rails 6 using fetch. My issue was solved by simply placing format.js above format.html. Thanks #holino. The following fetch works.
fetch(event.currentTarget.dataset.destroyPath, {
method: 'DELETE',
dataType: 'script',
credentials: 'include',
headers: {
'X-CSRF-Token': csrf
},
})

Not able to pass parameters through url in Ajax request using Rails

I'm trying to pass a parameter through a url in an Ajax request that's triggered by a confirmation dialogue. I'd like to fetch the value of that parameter in my Rails controller given a successful request but I haven't been able to do it.
I've tried so far the following code:
Here my Ajax request where I've been adding the param in the URL plus other params in data
function continueSave() {
var name = $('#leader_name').val();
var persisted_time = $('#leader_time').val();
$.ajax({
type: "POST",
url: "/leaderboards/1/?test=1",
data: { leader: { name: name, time: time } },
success: success
});
}
Here the dialogue-related JS
function nameAlert() {
return confirm("Name already exists. Would you like to continue?");
};
(function() {
if (nameAlert()) {
continueSave();
}
else {
//something else here
}
})();
Although the request successfully reaches the controller there's params[:test] is nil in the controller.
I've also tried to pass the test param in data, but it is not working either.
Would appreciate some help.
The relevant controller action (leaders_controller.rb)
def create
#leader = Leader.new(leader_params)
#leader.leaderboard_id = #leaderboard.id
#name_repeated = !#leaderboard.leaders.find_by(name: #leader.name).nil?
#check = params[:test]
if params[:test].nil? && #name_repeated == true
render :template => 'leaders/repeated_name.js.erb'
else
#leader.save
#rank = #leader.rank_in(#leaderboard)
respond_to do |format|
if #leader.save
format.html { redirect_to root_path }
format.js { }
else
end
end
end
end
Note:
1.- 'leaders/repeated_name.js.erb' contains the code for the Ajax request
2.- In routes Leader resource is nested within Leaderboard resource
Sorry guys I found the mistake. It was a dumb one.
I have shallow nested routes so that leaders is nested in leaderboards, therefore I was using the incorrect path for the request. It should be:
$.ajax({
type: "POST",
url: "/leaderboards/1/leaders?test=1",
data: { leader: { name: name, time: time } },
success: success
});
I should have caught that before sorry for wasting your time.
I'll post here - my comments are getting too long.
Try adding { type: 1} to your data and changing type to GET. Rails params contain both GET and POST data - you don't even have to change your controller.
function continueSave() {
var name = $('#leader_name').val();
var persisted_time = $('#leader_time').val();
$.ajax({
type: "GET",
url: "/leaderboards/1/",
data: { leader: { name: name, time: time }, test: 1 },
success: success
});
}

Render a view of controller A in every view of controller B via Ajax in rails

I have a Cart controller and a "show" view which shows the contents of the cart. I want to show the cart in every view of my Products controller. So, I'm rendering the cart/show in products/show using
<%= render "/cart/show" %>
Now, I want to update the cart via ajax when a user wants to add a product. Please guide me how I should design my controllers to achieve this.
How to use partials to DRY up your views.
http://guides.rubyonrails.org/layouts_and_rendering.html
function postToRailsApi() {
$.ajax({
type: "POST",
url: "the_url_you_want_to_post_to/endpoint",
data: {someData: {thisId: otherId}},
dataType: "json",
success: function(data) {
alert("OMG SUCCESS status:200")
}
});
In the rails controller:
respond_to do |format|
if #my_condition.save
format.html {render nothing: true, status:200}
format.js{render nothing: true, status:200}
format.json { render json: #timestamp, status: 200 }
else
format.html { render action: "new" }
format.js { render nothing: true, status: 400 }
format.json { render nothing: true, status: 400 }
end
end
Obviously your logic will be different.

Uncaught SyntaxError: Unexpected token u

I am trying to get a JSON response from a get request. However, I am getting the following error: Uncaught SyntaxError: Unexpected token u. I know the rails route works because I do get the response loaded successfully in the Console.
The Ajax Response is supposed to start when the checkbox changes and is checked.
Why am I getting this error from the $.parseJSON?
Rails Controller
def providers
#providers = User.order("last_name ASC, first_name ASC, middle_name ASC").where("provider_flag = ? and inactive_flag = ? and del_flag = ?", true, false, false).select("id, CONCAT(IFNULL(last_name,''), ', ', IFNULL(first_name,''), IFNULL(middle_name,'')) AS full_name");
respond_to do |format|
format.json { render :json => { :providers => #providers.to_json}, :status => :ok }
# format.json { render :json => #providers.to_json }
end
end
Javascript
$('#provider_chk').change(function() {
if($(this).is(":checked")) {
$.ajax({
url: '<%= providers_schedule_index_path %>',
type: 'GET',
dataType: 'json',
data: {
authenticity_token: $('meta[name=csrf-token]').attr('content')
},
success: function(data) {
console.log('loaded successfully.');
var providers = $.parseJSON(data.responseText)['providers'];
providers_count = $(providers).size();
console.log(providers);
console.log(providers_count);
},
error: function(data) {
console.log("An error has occurred!")
}
});
} else {
$('#providers_results').empty();
}
});
JSON Response
providers: "[{"id":2,"full_name":"Test, User"}]"
Your JSON response should look more like this:
providers: [{"id":2,"full_name":"Test, User"}]
The outermost quotations marks aren't needed.
If you really need the outer quote marks, you need to escape the inner ones.
In $.ajax({}), add the property "async:false". parseJSON hasn't gotten that JSON yet - it's immediately trying to operate on undefined ("u") and throwing the error.
Remove to_json since you are already telling rails to return json
format.json { render :json => { :providers => #providers }, :status => :ok }

Routing error in ajax on ruby on rails

I have this in my .html.erb code:
$.ajax({
url: "/timeMachineEdit",
data: {editTimeMachine: newArray},
type: 'POST',
success: function (res) {
if (res.result === 'ok') {
alert('Data saved');
} else {
alert('Save error');
}
},
error: function () {
alert('Save error.');
}
});
This in my datasets_controller.rb
def timeMachineEdit
#dataset = current_user.dataset
#dataset.machine_time = params[:editTimeMachine]
end
And in my routes.rb:
match "/timeMachineEdit", to: "datasets#timeMachineEdit"
But when is submited shows:
POST http://localhost:3000/timeMachineEdit 500 (Internal Server Error)
Where is the problem here?
is the routes in the ajax url or something else?
The problem is in your route definition....
try match "/timeMachineEdit", to: "datasets#timeMachineEdit"
I think, it will still not work because of the nature of format..In the datasets_controller try the following code...
def timeMachineEdit
#dataset = current_user.dataset
#dataset.machine_time = params[:editTimeMachine]
respond_to do |format|
format.js
end
end
Also change the dataType of your AJAX request to "script" in order to correctly match it with format.js else the format will be / which will select the first format that you will specify in the respond_to block..

Categories

Resources