diff --git a/lib/Instance.js b/lib/Instance.js index ef049d38..7b17a79b 100755 --- a/lib/Instance.js +++ b/lib/Instance.js @@ -65,22 +65,21 @@ function Instance(opts) { }; return checkNextValidation(); }; + var saveError = function (cb, err) { + emitEvent("save", err, instance); + Hook.trigger(instance, opts.hooks.afterSave, false); + if (typeof cb == "function") { + cb(err, instance); + } + }; var saveInstance = function (cb) { if (!opts.is_new && opts.changes.length === 0) { return saveInstanceExtra(cb); } - var saveError = function (err) { - emitEvent("save", err, instance); - Hook.trigger(instance, opts.hooks.afterSave, false); - if (typeof cb == "function") { - cb(err, instance); - } - }; - Hook.wait(instance, opts.hooks.beforeValidation, function (err) { if (err) { - return saveError(err); + return saveError(cb, err); } for (var k in opts.properties) { @@ -103,11 +102,11 @@ function Instance(opts) { if (opts.is_new) { return Hook.wait(instance, opts.hooks.beforeCreate, function (err) { if (err) { - return saveError(err); + return saveError(cb, err); } Hook.wait(instance, opts.hooks.beforeSave, function (err) { if (err) { - return saveError(err); + return saveError(cb, err); } return saveInstanceNext(cb); }); @@ -115,7 +114,7 @@ function Instance(opts) { } Hook.wait(instance, opts.hooks.beforeSave, function (err) { if (err) { - return saveError(err); + return saveError(cb, err); } return saveInstanceNext(cb); }); @@ -124,12 +123,7 @@ function Instance(opts) { var saveInstanceNext = function (cb) { handleValidations(function (err) { if (err) { - emitEvent("save", err, instance); - Hook.trigger(instance, opts.hooks.afterSave, err === null); - if (typeof cb == "function") { - cb(err, instance); - } - return; + return saveError(cb, err); } var data = {}; @@ -148,22 +142,27 @@ function Instance(opts) { if (opts.is_new) { opts.driver.insert(opts.table, data, opts.keys, function (save_err, info) { - if (!save_err) { - opts.changes.length = 0; - for (var i = 0; i < opts.keys.length; i++) { - opts.data[opts.keys[i]] = info[opts.keys[i]]; - } - opts.is_new = false; + if (save_err) { + return saveError(cb, save_err); } - emitEvent("save", save_err, instance); - Hook.trigger(instance, opts.hooks.afterCreate, !save_err); - Hook.trigger(instance, opts.hooks.afterSave, !save_err); - if (typeof cb == "function") { - if (save_err) { - return cb(save_err, instance); - } - return saveInstanceExtra(cb); + + opts.changes.length = 0; + for (var i = 0; i < opts.keys.length; i++) { + opts.data[opts.keys[i]] = info[opts.keys[i]]; } + opts.is_new = false; + + saveAssociations(function (err) { + emitEvent("save", err, instance); + Hook.trigger(instance, opts.hooks.afterCreate, !err); + Hook.trigger(instance, opts.hooks.afterSave, !err); + if (typeof cb == "function") { + if (err) { + return cb(err, instance); + } + return saveInstanceExtra(cb); + } + }); }); } else { var changes = {}, conditions = {}; @@ -174,21 +173,73 @@ function Instance(opts) { conditions[opts.keys[i]] = data[opts.keys[i]]; } opts.driver.update(opts.table, changes, conditions, function (save_err) { - if (!save_err) { - opts.changes.length = 0; + if (save_err) { + return saveError(cb, save_err); } - emitEvent("save", save_err, instance); - Hook.trigger(instance, opts.hooks.afterSave, !save_err); - if (typeof cb == "function") { - if (save_err) { - return cb(save_err, instance); + + opts.changes.length = 0; + + saveAssociations(function (err) { + emitEvent("save", err, instance); + Hook.trigger(instance, opts.hooks.afterSave, !err); + if (typeof cb == "function") { + if (err) { + return cb(err, instance); + } + return saveInstanceExtra(cb); } - return saveInstanceExtra(cb); - } + }); }); } }); }; + var saveAssociations = function (cb) { + var pending = 0, errored = false, i, j; + + for (i = 0; i < opts.one_associations.length; i++) { + if (!instance.hasOwnProperty(opts.one_associations[i].name)) continue; + + if (instance[opts.one_associations[i].name].isInstance) { + pending += 1; + + instance[opts.one_associations[i].setAccessor](instance[opts.one_associations[i].name], function (err) { + if (err) { + if (errored) return; + + errored = true; + return cb(err); + } + + if (--pending === 0) { + return cb(); + } + }); + } + } + + for (i = 0; i < opts.many_associations.length; i++) { + if (!instance.hasOwnProperty(opts.many_associations[i].name)) continue; + + pending += 1; + + instance[opts.many_associations[i].setAccessor](instance[opts.many_associations[i].name], function (err) { + if (err) { + if (errored) return; + + errored = true; + return cb(err); + } + + if (--pending === 0) { + return cb(); + } + }); + } + + if (pending === 0) { + return cb(); + } + }; var saveInstanceExtra = function (cb) { if (opts.extrachanges.length === 0) { if (cb) return cb(null, instance); @@ -422,6 +473,18 @@ function Instance(opts) { break; } } + for (i = 0; i < opts.one_associations.length; i++) { + if (opts.data.hasOwnProperty(opts.one_associations[i].name)) { + instance[opts.one_associations[i].name] = opts.data[opts.one_associations[i].name]; + delete opts.data[opts.one_associations[i].name]; + } + } + for (i = 0; i < opts.many_associations.length; i++) { + if (opts.data.hasOwnProperty(opts.many_associations[i].name)) { + instance[opts.many_associations[i].name] = opts.data[opts.many_associations[i].name]; + delete opts.data[opts.many_associations[i].name]; + } + } Hook.trigger(instance, opts.hooks.afterLoad); diff --git a/lib/Model.js b/lib/Model.js index cd6f8805..5347be62 100644 --- a/lib/Model.js +++ b/lib/Model.js @@ -31,10 +31,29 @@ function Model(opts) { inst_opts = {}; } - for (var k in data) { + var found_assoc = false, i, k; + + for (k in data) { if (k != "extra_field" && !opts.properties.hasOwnProperty(k) && opts.keys.indexOf(k) == -1 && association_properties.indexOf(k) == -1) { - delete data[k]; + found_assoc = false; + for (i = 0; i < one_associations.length; i++) { + if (one_associations[i].name == k) { + found_assoc = true; + break; + } + } + if (!found_assoc) { + for (i = 0; i < many_associations.length; i++) { + if (many_associations[i].name == k) { + found_assoc = true; + break; + } + } + } + if (!found_assoc) { + delete data[k]; + } } } @@ -53,6 +72,8 @@ function Model(opts) { hooks : opts.hooks, methods : opts.methods, validations : opts.validations, + one_associations : one_associations, + many_associations : many_associations, association_properties : association_properties }); if (model_fields !== null) {