Rewrite save and create for correct hooks order
Validation should be called first, and then all other actions to allow modify data after validation (for example hash password after validating length. Issue #242
This commit is contained in:
parent
48d78b71f6
commit
1f29064b3d
110
lib/model.js
110
lib/model.js
|
@ -171,38 +171,30 @@ AbstractClass.create = function (data, callback) {
|
|||
callback = function () {};
|
||||
}
|
||||
|
||||
var obj = null;
|
||||
var obj;
|
||||
// if we come from save
|
||||
if (data instanceof this && !data.id) {
|
||||
obj = data;
|
||||
data = obj.toObject(true);
|
||||
obj._initProperties(data, false);
|
||||
create();
|
||||
} else {
|
||||
obj = new this(data);
|
||||
}
|
||||
data = obj.toObject(true);
|
||||
|
||||
// validation required
|
||||
obj.isValid(function(valid) {
|
||||
if (valid) {
|
||||
create();
|
||||
} else {
|
||||
callback(new Error('Validation error'), obj);
|
||||
}
|
||||
}, data);
|
||||
|
||||
function create() {
|
||||
obj.trigger('create', function(createDone) {
|
||||
obj.trigger('save', function(saveDone) {
|
||||
|
||||
// validation required
|
||||
obj.isValid(function (valid) {
|
||||
if (!valid) {
|
||||
callback(new Error('Validation error'), obj);
|
||||
} else {
|
||||
create(saveDone);
|
||||
}
|
||||
});
|
||||
|
||||
}, obj);
|
||||
}
|
||||
|
||||
function create(saveDone) {
|
||||
obj.trigger('create', function (done) {
|
||||
|
||||
var data = this.toObject(true); // Added this to fix the beforeCreate trigger not fire.
|
||||
// The fix is per issue #72 and the fix was found by by5739.
|
||||
|
||||
this._adapter().create(modelName, this.constructor._forDB(data), function (err, id, rev) {
|
||||
obj._initProperties(data, false);
|
||||
if (id) {
|
||||
obj.__data.id = id;
|
||||
obj.__dataWas.id = id;
|
||||
|
@ -211,19 +203,17 @@ AbstractClass.create = function (data, callback) {
|
|||
if (rev) {
|
||||
obj._rev = rev
|
||||
}
|
||||
done.call(this, function () {
|
||||
if (saveDone) {
|
||||
if (err) {
|
||||
return callback(err, obj);
|
||||
}
|
||||
saveDone.call(obj, function () {
|
||||
if (callback) {
|
||||
createDone.call(obj, function () {
|
||||
callback(err, obj);
|
||||
}
|
||||
});
|
||||
} else if (callback) {
|
||||
callback(err, obj);
|
||||
}
|
||||
});
|
||||
}.bind(this));
|
||||
}, obj);
|
||||
});
|
||||
}, data);
|
||||
}, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -618,36 +608,42 @@ AbstractClass.prototype.save = function (options, callback) {
|
|||
options.throws = false;
|
||||
}
|
||||
|
||||
if (options.validate) {
|
||||
this.isValid(function (valid) {
|
||||
var inst = this;
|
||||
var data = inst.toObject(true);
|
||||
var Model = this.constructor;
|
||||
var modelName = Model.modelName;
|
||||
|
||||
if (!this.id) {
|
||||
return Model.create(this, callback);
|
||||
}
|
||||
|
||||
// validate first
|
||||
if (!options.validate) {
|
||||
return save();
|
||||
}
|
||||
|
||||
inst.isValid(function (valid) {
|
||||
if (valid) {
|
||||
save.call(this);
|
||||
save();
|
||||
} else {
|
||||
var err = new Error('Validation error');
|
||||
// throws option is dangerous for async usage
|
||||
if (options.throws) {
|
||||
throw err;
|
||||
}
|
||||
callback(err, this);
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
save.call(this);
|
||||
callback(err, inst);
|
||||
}
|
||||
});
|
||||
|
||||
// then save
|
||||
function save() {
|
||||
this.trigger('save', function (saveDone) {
|
||||
var modelName = this.constructor.modelName;
|
||||
var data = this.toObject(true);
|
||||
var inst = this;
|
||||
if (inst.id) {
|
||||
inst.trigger('save', function (saveDone) {
|
||||
inst.trigger('update', function (updateDone) {
|
||||
inst._adapter().save(modelName, inst.constructor._forDB(data), function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
} else {
|
||||
inst._initProperties(data, false);
|
||||
return callback(err, inst);
|
||||
}
|
||||
inst._initProperties(data, false);
|
||||
updateDone.call(inst, function () {
|
||||
saveDone.call(inst, function () {
|
||||
callback(err, inst);
|
||||
|
@ -655,15 +651,7 @@ AbstractClass.prototype.save = function (options, callback) {
|
|||
});
|
||||
});
|
||||
}, data);
|
||||
} else {
|
||||
inst.constructor.create(inst, function (err) {
|
||||
saveDone.call(inst, function () {
|
||||
callback(err, inst);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}, this);
|
||||
}, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -784,15 +772,15 @@ AbstractClass.prototype.updateAttributes = function updateAttributes(data, cb) {
|
|||
inst[key] = data[key];
|
||||
});
|
||||
|
||||
inst.trigger('save', function (saveDone) {
|
||||
inst.trigger('update', function (done) {
|
||||
|
||||
inst.isValid(function (valid) {
|
||||
if (!valid) {
|
||||
if (cb) {
|
||||
cb(new Error('Validation error'), inst);
|
||||
}
|
||||
} else {
|
||||
inst.trigger('save', function (saveDone) {
|
||||
inst.trigger('update', function (done) {
|
||||
|
||||
Object.keys(data).forEach(function (key) {
|
||||
inst[key] = data[key];
|
||||
});
|
||||
|
@ -810,10 +798,10 @@ AbstractClass.prototype.updateAttributes = function updateAttributes(data, cb) {
|
|||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}, data);
|
||||
}, data);
|
||||
}
|
||||
}, data);
|
||||
};
|
||||
|
||||
AbstractClass.prototype.fromObject = function (obj) {
|
||||
|
|
Loading…
Reference in New Issue