I am trying to use ember-data to get a simple registration form to save on my server. The call technically works, but the success callback is never trigger on the promise, and I have no idea why.
The server receives the data from the front end and successfully saves it to the database. It then returns status code 201 for CREATED. I can see the successful response happening in the Chrome debugger. But even when the server responds with a successful status, the error callback is triggered on the save's promise. I've confirmed this happens every time by putting a debugger; statement in the error callback.
My router's model is hooked up like this:
model: function() {
return this.store.createRecord('registerUser');
}
And I have a simple register function in my controller:
register: function() {
var self = this;
this.get('model').save().then(function() {
self.transitionToRoute('index');
}, function(resp) {
if (resp.responseJSON) {
self.get('model').set('errors', resp.responseJSON.errors);
}
});
}
Every time my server comes back with a response, success or failure, the failure callback is hit. If I have errors in the response (for invalid data or something), the errors are successfully displayed in the form. I can see the request coming in properly, and the data is stored in the database. So, the save is technically successful, but ember doesn't seem to know that it is even though a successful 201 status is returned from the server (which can be verified in the Chrome debugger).
The only thing I can think of is that ember-data's adapter is doing something that I'm not aware of, but I am just using the default RESTAdapter and haven't touched it. Is there anything else
If it makes a difference, the server is running Play 1.2.5. I don't know if that makes a difference in the response's header or something like that.
Any help would be greatly appreciated. Thank you for your time!
Mike
SOLUTION
So, the issue was to do with the JSON response. The two problems:
I did not include an ID in the response
I did not "wrap" the response in a "registerUser". This is necessary to match the model name.
Below is a valid response:
{
"registerUser": {
"id": 11,
"email": "mike999#test.com",
"password": "12345",
"password2": "12345",
"name": "Mike"
}
}
Ember Data is expecting the model in the response, so sending back a success http status doesn't mean it will hit the success endpoint. When it tries to serialize your response (or lack of response) it's probably failing which would be why it's hitting the failure function. A big reason for the response is the id of the record.
The model returned should be in the following format
{
registerUser:{
id: "123",
attr: "asdf"
}
}
https://github.com/emberjs/data/blob/master/TRANSITION.md
Related
When I call myModel.save(), in one of my controllers, to insert a new record into the store I get back a promise with isRejected: true.
The reason object has the following attributes:
readyState: 4,
status: 201,
statusText: "created"
The object is created properly in my backend REST service. In fact, if I put the transitionToRoute in the catch(), instead of the then(), everything would appear to be just fine.
What's going on here?
You need to return the object back with your request. This is particularly important because the server should provide an id for that newly created record. Without an id there is no definitive way of updating and being sure you're updating the correct record. The format should follow the same format if you were to find the model.
IE:
{
type: {
id:12312,
property:'value',
otherProperty:'value'
}
}
I am implementing error logging in my EmberJS application much as is described here and it's working pretty well. The only part that is throwing me off is how to properly handle error calls from the Ember RSVP onerror event.
Errors produced from within the Ember run loop are nicely formatted with message and stack properties, but errors raised from RSVP give back a standard XHR response and no additional context. Is it possible to access any information about what Ajax call was being executed when this error occurred?
I am using Ember 1.3.1 and Ember Data 1.0.0+b6.
I'm using a dirty workaround to get context from RSVP internals. You can overwrite RVSP.Promise._onerror method and include some data. 'this' object has _label property which contains sometime useful info about model.
My solution is still not ideal but it is something.
#RSVP _onerror hack
#put this before creating application
oldMethod = Em.RSVP.Promise.prototype._onerror
Em.RSVP.Promise.prototype._onerror = (reason) ->
reason.label = this._label
oldMethod(reason)
App = Ember.Application.create(options)
And little improved code to hook on standart onerror method
Ember.RSVP.configure('onerror', (error) ->
#handle situation when user in other tab logout from application.
if error.status == 401 #not authorized
window.location = '/login'
else
niceError = unless error.stack
message = {
label: error.label,
status: error.status,
statusText: error.statusText,
state: error.state(),
readyState: error.readyState,
responseText: error.responseText.replace(/<(?:.|\n)*?>/gm, '').substr(0,100)
}
new Error(Ember.inspect(message))
else
error
#here is method to send notification about error
MessageApp.errorHandler('RSVP', niceError)
I would like to request a 'reset password' endpoint e.g GET -> user/password/reset on an API. What is the best way to map this request in ember.js? It doesn't seem appropriate to setup a full ember.js model for this kind of request, as it doesn't have a proper ID and is not really a request for a record, but a triggered event with a success/fail response. Am I incorrectly implementing the REST convention or is there another way to do this?
You can use a simple ember-object to represent password reset and then basic ajax. Something like this:
App.User.reopenClass({
resetPassword: function(subreddit) {
return $.getJSON("user/password/reset").then(
function(response) {
console.log('it worked');
return true;
},
function(response) {
console.log('fail');
return false;
}
);
}
});
See http://eviltrout.com/2013/03/23/ember-without-data.html
That said, this could be a sign that the API endpoint should change. Ideally GET requests should not have side effects, so a GET that resets a password is not recommended. If you think of reset as a password reset request, the reset password endpoint that makes the most sense is POST -> user/password/reset to create a new request.
I've gotten the built in read action to work in the past but now it is not working. I also created a custom action which will not work.
When I try to post the action to this url:
https://graph.facebook.com/me/teamtutorials:complete?access_token=AAACOYImsskcBAGlF33o6awIqxmQ078BVdHUY72CF7GUqTHUhEcpKLdH8ZCKeyQbBqBDlnHwUMwt5aLOzpBmiWQqpvWsNAeHDMPSo2OQZDZD&tutorial=http://teamtutorials.com/web-development-tutorials/why-zen-coding-is-an-awesome-time-saver?
all I get in response is:
{
"data": [
],
"paging": {
"next": "https://graph.facebook.com/me/teamtutorials:complete?access_token=AAACOYImsskcBAGlF33o6awIqxmQ078BVdHUY72CF7GUqTHUhEcpKLdH8ZCKeyQbBqBDlnHwUMwt5aLOzpBmiWQqpvWsNAeHDMPSo2OQZDZD&tutorial=http\u00253A\u00252F\u00252Fteamtutorials.com\u00252Fweb-development-tutorials\u00252Fwhy-zen-coding-is-an-awesome-time-saver\u00253F&offset=25&limit=25"
}
}
What causes this type of response?
That looks like the response you'd get to a HTTP GET request; you need to make a HTTP POST request to create a new action
if your code/proxy can't make POST request outbound or you can fake it by making a GET request and including an extra parameter &method=post
Say I am running stumbleupon.com and users can submit sites to be added into the db of sites. Is there a way that I can write a program to see whether or not the site that was added by the user is actually a real website? Or if it bring me to a 404 that I can say "welp, that was some bugus" or maybe that the user made an error when submitting the url? Or do i need to put people on my payroll to see if the user submitted website bring me to a 404?
The response code from the request is a 404 not found, instead of a 200 success message that you get on a good response from the server. You can easily automate the check.
Since I don't know much about python, I offer a client side solution.
You could check if the URL is legit as soon as the user submits the page. Maybe throw up a 'verifying url' message or something.
Using this method you could make a cross domain call to see if that site is really there. Then you could pop up a message that asks them to fix their mistake or allow the URL to be submitted. This solution uses Yahoo as a proxy, but as you can see by my super simple function below it does work.
function doAjaxCheck(url){
// if the URL starts with http
if(url.match('^http')){
//add a 'loading message here, or something'
// assemble the YQL call
$.getJSON("http://query.yahooapis.com/v1/public/yql?"+
"q=select%20*%20from%20html%20where%20url%3D%22"+
encodeURIComponent(url)+
"%22&format=xml'&callback=?",
function(data){
if(data.results[0]){
alert('it is OK');
} else {
alert('not OK');
}
}
);
} else {
$.ajax({
url: url,
timeout:5000,
success: function(data){
alert('it is OK');
},
error: function(req,error){
if(error === 'error'){error = req.statusText;}
alert('not OK : ' + error );
}
});
}
}
However, all this being said, I would go with a server-side check for reliability-sake.