mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
Fix promise rejection
fixes #3013 - bubble promise rejection on post model validation/save error so that it doesn't bubble as resolved - prefer `.catch()` for promise handlers as per recommendations - check if `.save()` is being called from model.destroyRecord() and forgo validation if so - normalize output for both `.validate()` and `.save()`
This commit is contained in:
parent
aa9dfd97d1
commit
1f9751f753
5 changed files with 47 additions and 27 deletions
|
@ -14,8 +14,8 @@ var LeaveEditorController = Ember.Controller.extend({
|
||||||
model = editorController.get('model');
|
model = editorController.get('model');
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO: throw some kind of error here? return true will send it upward?
|
|
||||||
if (!transition || !editorController) {
|
if (!transition || !editorController) {
|
||||||
|
this.notifications.showError('Sorry, there was an error in the application. Please let the Ghost team know what happened.');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,9 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
self.notifications.showSuccess('Successfully converted to ' + (val ? 'static page' : 'post'));
|
self.notifications.showSuccess('Successfully converted to ' + (val ? 'static page' : 'post'));
|
||||||
|
|
||||||
return self.get('page');
|
return self.get('page');
|
||||||
}, function (errors) {
|
}).catch(function (errors) {
|
||||||
self.notifications.showErrors(errors);
|
self.notifications.showErrors(errors);
|
||||||
|
return Ember.RSVP.reject(errors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,8 +138,9 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
return self.get('model').save().then(function () {
|
return self.get('model').save().then(function () {
|
||||||
self.notifications.showSuccess('Permalink successfully changed to <strong>' +
|
self.notifications.showSuccess('Permalink successfully changed to <strong>' +
|
||||||
self.get('slug') + '</strong>.');
|
self.get('slug') + '</strong>.');
|
||||||
}, function (errors) {
|
}).catch(function (errors) {
|
||||||
self.notifications.showErrors(errors);
|
self.notifications.showErrors(errors);
|
||||||
|
return Ember.RSVP.reject(errors);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -190,8 +192,9 @@ var PostSettingsMenuController = Ember.ObjectController.extend({
|
||||||
this.get('model').save().then(function () {
|
this.get('model').save().then(function () {
|
||||||
self.notifications.showSuccess('Publish date successfully changed to <strong>' +
|
self.notifications.showSuccess('Publish date successfully changed to <strong>' +
|
||||||
formatDate(self.get('published_at')) + '</strong>.');
|
formatDate(self.get('published_at')) + '</strong>.');
|
||||||
}, function (errors) {
|
}).catch(function (errors) {
|
||||||
self.notifications.showErrors(errors);
|
self.notifications.showErrors(errors);
|
||||||
|
return Ember.RSVP.reject(errors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ var PostController = Ember.ObjectController.extend({
|
||||||
self.notifications.showSuccess('Post successfully marked as ' + (featured ? 'featured' : 'not featured') + '.');
|
self.notifications.showSuccess('Post successfully marked as ' + (featured ? 'featured' : 'not featured') + '.');
|
||||||
}).catch(function (errors) {
|
}).catch(function (errors) {
|
||||||
self.notifications.showErrors(errors);
|
self.notifications.showErrors(errors);
|
||||||
|
return Ember.RSVP.reject(errors);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,6 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, {
|
||||||
actions: {
|
actions: {
|
||||||
save: function () {
|
save: function () {
|
||||||
var status = this.get('willPublish') ? 'published' : 'draft',
|
var status = this.get('willPublish') ? 'published' : 'draft',
|
||||||
model = this.get('model'),
|
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
// set markdown equal to what's in the editor, minus the image markers.
|
// set markdown equal to what's in the editor, minus the image markers.
|
||||||
|
@ -117,7 +116,7 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, {
|
||||||
|
|
||||||
this.set('status', status);
|
this.set('status', status);
|
||||||
|
|
||||||
return model.save().then(function () {
|
return this.get('model').save().then(function (model) {
|
||||||
model.updateTags();
|
model.updateTags();
|
||||||
// `updateTags` triggers `isDirty => true`.
|
// `updateTags` triggers `isDirty => true`.
|
||||||
// for a saved model it would otherwise be false.
|
// for a saved model it would otherwise be false.
|
||||||
|
@ -126,8 +125,9 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, {
|
||||||
self.notifications.showSuccess('Post status saved as <strong>' +
|
self.notifications.showSuccess('Post status saved as <strong>' +
|
||||||
model.get('status') + '</strong>.');
|
model.get('status') + '</strong>.');
|
||||||
return model;
|
return model;
|
||||||
}, function (errors) {
|
}).catch(function (errors) {
|
||||||
self.notifications.showErrors(errors);
|
self.notifications.showErrors(errors);
|
||||||
|
return Ember.RSVP.reject(errors);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ var ValidationEngine = Ember.Mixin.create({
|
||||||
|
|
||||||
return new Ember.RSVP.Promise(function (resolve, reject) {
|
return new Ember.RSVP.Promise(function (resolve, reject) {
|
||||||
if (!type || !validator) {
|
if (!type || !validator) {
|
||||||
return reject('The validator specified, "' + type + '", did not exist!');
|
return reject(self.formatErrors('The validator specified, "' + type + '", did not exist!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var validationErrors = validator.validate(self);
|
var validationErrors = validator.validate(self);
|
||||||
|
@ -26,10 +26,33 @@ var ValidationEngine = Ember.Mixin.create({
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return reject(validationErrors);
|
return reject(self.formatErrors(validationErrors));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// format errors to be used in `notifications.showErrors`.
|
||||||
|
// format is [{ message: 'concatenated error messages' }]
|
||||||
|
formatErrors: function (errors) {
|
||||||
|
var message = 'There was an error saving this ' + this.get('validationType');
|
||||||
|
|
||||||
|
if (Ember.isArray(errors)) {
|
||||||
|
// get validation error messages
|
||||||
|
message += ': ' + errors.mapBy('message').join(' ');
|
||||||
|
} else if (typeof errors === 'object') {
|
||||||
|
// Get messages from server response
|
||||||
|
message += ': ' + getRequestErrorMessage(errors);
|
||||||
|
} else if (typeof errors === 'string') {
|
||||||
|
message += ': ' + errors;
|
||||||
|
} else {
|
||||||
|
message += '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// set format for notifications.showErrors
|
||||||
|
message = [{ message: message }];
|
||||||
|
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
// override save to do validation first
|
// override save to do validation first
|
||||||
save: function () {
|
save: function () {
|
||||||
var self = this,
|
var self = this,
|
||||||
|
@ -37,31 +60,24 @@ var ValidationEngine = Ember.Mixin.create({
|
||||||
// ref: https://github.com/emberjs/ember.js/pull/4301
|
// ref: https://github.com/emberjs/ember.js/pull/4301
|
||||||
_super = this.__nextSuper;
|
_super = this.__nextSuper;
|
||||||
|
|
||||||
|
// model.destroyRecord() calls model.save() behind the scenes.
|
||||||
|
// in that case, we don't need validation checks or error propagation.
|
||||||
|
if (this.get('isDeleted')) {
|
||||||
|
return this._super();
|
||||||
|
}
|
||||||
|
|
||||||
// If validation fails, reject with validation errors.
|
// If validation fails, reject with validation errors.
|
||||||
// If save to the server fails, reject with server response.
|
// If save to the server fails, reject with server response.
|
||||||
return this.validate().then(function () {
|
return this.validate().then(function () {
|
||||||
return _super.call(self);
|
return _super.call(self);
|
||||||
}).catch(function (result) {
|
}).catch(function (result) {
|
||||||
var message = 'There was an error saving this ' + self.get('validationType');
|
// server save failed, format the errors and reject the promise.
|
||||||
|
// if validations failed, the errors will already be formatted for us.
|
||||||
if (Ember.isArray(result)) {
|
if (! Ember.isArray(result)) {
|
||||||
// get validation error messages
|
result = self.formatErrors(result);
|
||||||
message += ': ' + result.mapBy('message').join(' ');
|
|
||||||
} else if (typeof result === 'object') {
|
|
||||||
// Get messages from server response
|
|
||||||
message += ': ' + getRequestErrorMessage(result);
|
|
||||||
} else if (typeof result === 'string') {
|
|
||||||
message += ': ' + result;
|
|
||||||
} else {
|
|
||||||
message += '.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set format for notifications.showErrors
|
return Ember.RSVP.reject(result);
|
||||||
message = [{ message: message }];
|
|
||||||
|
|
||||||
return new Ember.RSVP.Promise(function (resolve, reject) {
|
|
||||||
reject(message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue