BVB Source Codes

waterline Show destroy.js Source code

Return Download waterline: download destroy.js Source code - Download waterline Source code - Type:.js
  1. /**
  2.  * Module Dependencies
  3.  */
  4.  
  5. var async = require('async');
  6. var util = require('util');
  7. var async = require('async');
  8. var _ = require('@sailshq/lodash');
  9. var flaverr = require('flaverr');
  10. var forgeStageTwoQuery = require('../utils/query/forge-stage-two-query');
  11. var forgeStageThreeQuery = require('../utils/query/forge-stage-three-query');
  12. var Deferred = require('../utils/query/deferred');
  13. var processAllRecords = require('../utils/records/process-all-records');
  14.  
  15.  
  16. /**
  17.  * Destroy records matching the criteria.
  18.  *
  19.  * @param {Dictionary} criteria to destroy
  20.  * @param {Function} callback
  21.  * @return {Deferred} if no callback
  22.  */
  23.  
  24. module.exports = function destroy(criteria, done, metaContainer) {
  25.  
  26.   // Set up a few, common local vars for convenience / familiarity.
  27.   var WLModel = this;
  28.   var orm = this.waterline;
  29.   var modelIdentity = this.identity;
  30.  
  31.   //  鈻堚枅鈺   鈻堚枅鈺 鈻堚枅鈻堚枅鈻堚晽 鈻堚枅鈻堚枅鈻堚枅鈺 鈻堚枅鈺 鈻堚枅鈻堚枅鈻堚晽 鈻堚枅鈻堚枅鈻堚枅鈺 鈻堚枅鈺 鈻堚枅鈻堚枅鈻堚枅鈺椻枅鈻堚枅鈻堚枅鈻堚枅鈺
  32.   //  鈻堚枅鈺   鈻堚枅鈺戔枅鈻堚晹鈺愨晲鈻堚枅鈺椻枅鈻堚晹鈺愨晲鈻堚枅鈺椻枅鈻堚晳鈻堚枅鈺斺晲鈺愨枅鈻堚晽鈻堚枅鈺斺晲鈺愨枅鈻堚晽鈻堚枅鈺戔枅鈻堚晹鈺愨晲鈺愨晲鈺濃枅鈻堚晹鈺愨晲鈺愨晲鈺
  33.   //  鈻堚枅鈺   鈻堚枅鈺戔枅鈻堚枅鈻堚枅鈻堚枅鈺戔枅鈻堚枅鈻堚枅鈻堚晹鈺濃枅鈻堚晳鈻堚枅鈻堚枅鈻堚枅鈻堚晳鈻堚枅鈺  鈻堚枅鈺戔枅鈻堚晳鈻堚枅鈺     鈻堚枅鈻堚枅鈻堚枅鈻堚晽
  34.   //  鈺氣枅鈻堚晽 鈻堚枅鈺斺暆鈻堚枅鈺斺晲鈺愨枅鈻堚晳鈻堚枅鈺斺晲鈺愨枅鈻堚晽鈻堚枅鈺戔枅鈻堚晹鈺愨晲鈻堚枅鈺戔枅鈻堚晳  鈻堚枅鈺戔枅鈻堚晳鈻堚枅鈺     鈺氣晲鈺愨晲鈺愨枅鈻堚晳
  35.   //   鈺氣枅鈻堚枅鈻堚晹鈺 鈻堚枅鈺  鈻堚枅鈺戔枅鈻堚晳  鈻堚枅鈺戔枅鈻堚晳鈻堚枅鈺  鈻堚枅鈺戔枅鈻堚枅鈻堚枅鈻堚晹鈺濃枅鈻堚晳鈺氣枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈻堚枅鈻堚枅鈻堚晳
  36.   //    鈺氣晲鈺愨晲鈺  鈺氣晲鈺  鈺氣晲鈺濃暁鈺愨暆  鈺氣晲鈺濃暁鈺愨暆鈺氣晲鈺  鈺氣晲鈺濃暁鈺愨晲鈺愨晲鈺愨暆 鈺氣晲鈺 鈺氣晲鈺愨晲鈺愨晲鈺濃暁鈺愨晲鈺愨晲鈺愨晲鈺
  37.   //
  38.   // FUTURE: when time allows, update this to match the "VARIADICS" format
  39.   // used in the other model methods.
  40.  
  41.  
  42.   if (typeof criteria === 'function') {
  43.     done = criteria;
  44.     criteria = {};
  45.   }
  46.  
  47.   //  鈻堚枅鈻堚枅鈻堚枅鈺 鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈻堚枅鈻堚枅鈺
  48.   //  鈻堚枅鈺斺晲鈺愨枅鈻堚晽鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈻堚枅鈺斺晲鈺愨枅鈻堚晽
  49.   //  鈻堚枅鈺  鈻堚枅鈺戔枅鈻堚枅鈻堚枅鈺  鈻堚枅鈻堚枅鈻堚晽  鈻堚枅鈻堚枅鈻堚晽  鈻堚枅鈻堚枅鈻堚枅鈺斺暆
  50.   //  鈻堚枅鈺  鈻堚枅鈺戔枅鈻堚晹鈺愨晲鈺  鈻堚枅鈺斺晲鈺愨暆  鈻堚枅鈺斺晲鈺愨暆  鈻堚枅鈺斺晲鈺愨枅鈻堚晽
  51.   //  鈻堚枅鈻堚枅鈻堚枅鈺斺暆鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈺     鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈺  鈻堚枅鈺
  52.   //  鈺氣晲鈺愨晲鈺愨晲鈺 鈺氣晲鈺愨晲鈺愨晲鈺愨暆鈺氣晲鈺     鈺氣晲鈺愨晲鈺愨晲鈺愨暆鈺氣晲鈺  鈺氣晲鈺
  53.   //
  54.   //   鈻堚枅鈺椻枅鈻堚枅鈺   鈻堚枅鈻堚晽 鈻堚枅鈻堚枅鈻堚晽 鈻堚枅鈺   鈻堚枅鈺椻枅鈻堚枅鈻堚枅鈻堚晽 鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈺
  55.   //  鈻堚枅鈺斺暆鈻堚枅鈻堚枅鈺 鈻堚枅鈻堚枅鈺戔枅鈻堚晹鈺愨晲鈻堚枅鈺椻暁鈻堚枅鈺 鈻堚枅鈺斺暆鈻堚枅鈺斺晲鈺愨枅鈻堚晽鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈺氣枅鈻堚晽
  56.   //  鈻堚枅鈺 鈻堚枅鈺斺枅鈻堚枅鈻堚晹鈻堚枅鈺戔枅鈻堚枅鈻堚枅鈻堚枅鈺 鈺氣枅鈻堚枅鈻堚晹鈺 鈻堚枅鈻堚枅鈻堚枅鈺斺暆鈻堚枅鈻堚枅鈻堚晽   鈻堚枅鈺
  57.   //  鈻堚枅鈺 鈻堚枅鈺戔暁鈻堚枅鈺斺暆鈻堚枅鈺戔枅鈻堚晹鈺愨晲鈻堚枅鈺  鈺氣枅鈻堚晹鈺  鈻堚枅鈺斺晲鈺愨枅鈻堚晽鈻堚枅鈺斺晲鈺愨暆   鈻堚枅鈺
  58.   //  鈺氣枅鈻堚晽鈻堚枅鈺 鈺氣晲鈺 鈻堚枅鈺戔枅鈻堚晳  鈻堚枅鈺   鈻堚枅鈺   鈻堚枅鈻堚枅鈻堚枅鈺斺暆鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈺斺暆
  59.   //   鈺氣晲鈺濃暁鈺愨暆     鈺氣晲鈺濃暁鈺愨暆  鈺氣晲鈺   鈺氣晲鈺   鈺氣晲鈺愨晲鈺愨晲鈺 鈺氣晲鈺愨晲鈺愨晲鈺愨暆鈺氣晲鈺
  60.   //
  61.   //  鈹屸攼 鈹 鈹敩鈹  鈹屸敩鈹   鈹   鈹攢鈹愨攲鈹€鈹愨攲鈹攼鈹 鈹敩鈹€鈹愨攲鈹愨攲  鈹屸攼鈹屸攲鈹€鈹愨敩 鈹  鈹屸敩鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨敩鈹€鈹愨敩鈹€鈹愨攲鈹€鈹愨攲鈹攼
  62.   //  鈹溾敶鈹愨攤 鈹傗攤鈹   鈹傗攤  鈹屸敿鈹€  鈹溾敩鈹樷敎鈹  鈹 鈹 鈹傗敎鈹敇鈹傗攤鈹  鈹傗攤鈹傗敎鈹 鈹傗攤鈹   鈹傗攤鈹溾敜 鈹溾敜 鈹溾敜 鈹溾敩鈹樷敎鈹敇鈹溾敜  鈹傗攤
  63.   //  鈹斺攢鈹樷敂鈹€鈹樷敶鈹粹攢鈹樷攢鈹粹敇  鈹斺敇   鈹粹敂鈹€鈹斺攢鈹 鈹 鈹斺攢鈹樷敶鈹斺攢鈹樷敂鈹  鈹樷敂鈹樷敂鈹€鈹樷敂鈹粹敇  鈹€鈹粹敇鈹斺攢鈹樷敂  鈹斺攢鈹樷敶鈹斺攢鈹粹敂鈹€鈹斺攢鈹樷攢鈹粹敇
  64.   //  鈹屸攢    鈹攲鈹€鈹  鈹攢鈹愨攲鈹€鈹愨敩  鈹屸攢鈹愨敩  鈹攲鈹€鈹愨攲鈹愨攲鈹屸敩鈹    鈹€鈹
  65.   //  鈹傗攢鈹€鈹€  鈹傗敎鈹   鈹溾敩鈹樷敎鈹 鈹  鈹溾敜 鈹斺攼鈹屸敇鈹溾攢鈹も攤鈹傗攤 鈹   鈹€鈹€鈹€鈹
  66.   //  鈹斺攢    鈹粹敂    鈹粹敂鈹€鈹斺攢鈹樷敶鈹€鈹樷敂鈹€鈹 鈹斺敇 鈹 鈹粹敇鈹斺敇 鈹     鈹€鈹
  67.   // Return Deferred or pass to adapter
  68.   if (typeof done !== 'function') {
  69.     return new Deferred(WLModel, WLModel.destroy, {
  70.       method: 'destroy',
  71.       criteria: criteria
  72.     });
  73.   }
  74.  
  75.   // Otherwise, IWMIH, we know that a callback was specified.
  76.   // So...
  77.   //
  78.   //  鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈺  鈻堚枅鈺椻枅鈻堚枅鈻堚枅鈻堚枅鈺 鈻堚枅鈻堚枅鈻堚枅鈺椻枅鈻堚晽   鈻堚枅鈺椻枅鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈻堚枅鈻堚枅鈻堚晽
  79.   //  鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈺氣枅鈻堚晽鈻堚枅鈺斺暆鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈻堚枅鈺斺晲鈺愨晲鈺愨暆鈻堚枅鈺   鈻堚枅鈺戔暁鈺愨晲鈻堚枅鈺斺晲鈺愨暆鈻堚枅鈺斺晲鈺愨晲鈺愨暆
  80.   //  鈻堚枅鈻堚枅鈻堚晽   鈺氣枅鈻堚枅鈺斺暆 鈻堚枅鈻堚枅鈻堚晽  鈻堚枅鈺     鈻堚枅鈺   鈻堚枅鈺   鈻堚枅鈺   鈻堚枅鈻堚枅鈻堚晽
  81.   //  鈻堚枅鈺斺晲鈺愨暆   鈻堚枅鈺斺枅鈻堚晽 鈻堚枅鈺斺晲鈺愨暆  鈻堚枅鈺     鈻堚枅鈺   鈻堚枅鈺   鈻堚枅鈺   鈻堚枅鈺斺晲鈺愨暆
  82.   //  鈻堚枅鈻堚枅鈻堚枅鈻堚晽鈻堚枅鈺斺暆 鈻堚枅鈺椻枅鈻堚枅鈻堚枅鈻堚枅鈺椻暁鈻堚枅鈻堚枅鈻堚枅鈺椻暁鈻堚枅鈻堚枅鈻堚枅鈺斺暆   鈻堚枅鈺   鈻堚枅鈻堚枅鈻堚枅鈻堚晽
  83.   //  鈺氣晲鈺愨晲鈺愨晲鈺愨暆鈺氣晲鈺  鈺氣晲鈺濃暁鈺愨晲鈺愨晲鈺愨晲鈺 鈺氣晲鈺愨晲鈺愨晲鈺 鈺氣晲鈺愨晲鈺愨晲鈺    鈺氣晲鈺   鈺氣晲鈺愨晲鈺愨晲鈺愨暆
  84.  
  85.   //  鈺斺晲鈺椻晹鈺愨晽鈺︹晲鈺椻晹鈺愨晽鈺斺晲鈺  鈹屸攢鈹愨攲鈹攼鈹屸攢鈹愨攲鈹€鈹愨攲鈹€鈹  鈹屸敩鈹愨敩 鈹攲鈹€鈹  鈹屸攢鈹 鈹 鈹攲鈹€鈹愨敩鈹€鈹愨敩 鈹
  86.   //  鈺犫暎 鈺 鈺戔暊鈺︹暆鈺 鈺︹晳鈺   鈹斺攢鈹 鈹 鈹溾攢鈹も攤 鈹敎鈹    鈹 鈹傗攤鈹傗攤 鈹  鈹傗攢鈹尖攼鈹 鈹傗敎鈹 鈹溾敩鈹樷敂鈹敇
  87.   //  鈺  鈺氣晲鈺濃暕鈺氣晲鈺氣晲鈺濃暁鈺愨暆  鈹斺攢鈹 鈹 鈹 鈹粹敂鈹€鈹樷敂鈹€鈹   鈹 鈹斺敶鈹樷敂鈹€鈹  鈹斺攢鈹樷敂鈹斺攢鈹樷敂鈹€鈹樷敶鈹斺攢 鈹
  88.   //
  89.   // Forge a stage 2 query (aka logical protostatement)
  90.   // This ensures a normalized format.
  91.   var query = {
  92.     method: 'destroy',
  93.     using: modelIdentity,
  94.     criteria: criteria,
  95.     meta: metaContainer
  96.   };
  97.  
  98.   try {
  99.     forgeStageTwoQuery(query, orm);
  100.   } catch (e) {
  101.     switch (e.code) {
  102.       case 'E_INVALID_CRITERIA':
  103.         return done(
  104.           flaverr(
  105.             { name: 'UsageError' },
  106.             new Error(
  107.               'Invalid criteria.\n'+
  108.               'Details:\n'+
  109.               '  '+e.details+'\n'
  110.             )
  111.           )
  112.         );
  113.  
  114.       case 'E_NOOP':
  115.         // Determine the appropriate no-op result.
  116.         // If `fetch` meta key is set, use `[]`-- otherwise use `undefined`.
  117.         //
  118.         // > Note that future versions might simulate output from the raw driver.
  119.         // > (e.g. `{ numRecordsDestroyed: 0 }`)
  120.         // >  See: https://github.com/treelinehq/waterline-query-docs/blob/master/docs/results.md#destroy
  121.         var noopResult = undefined;
  122.         if (query.meta && query.meta.fetch) {
  123.           noopResult = [];
  124.         }//>-
  125.         return done(undefined, noopResult);
  126.  
  127.       default:
  128.         return done(e);
  129.     }
  130.   }
  131.  
  132.  
  133.   //  鈺 鈺︹晹鈺愨晽鈺斺晽鈺斺晹鈺︹晽鈺  鈺斺晲鈺        鈹  鈹攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨敩 鈹攲鈹€鈹愨敩  鈹屸攢鈹  鈹屸攢鈹愨攲鈹€鈹愨敩  鈹  鈹屸攼 鈹屸攢鈹愨攲鈹€鈹愨敩鈹屸攢
  134.   //  鈺犫晲鈺b暊鈺愨暎鈺戔晳鈺 鈺戔晳鈺  鈺戔暎  BEFORE 鈹  鈹傗敎鈹 鈹溾敜 鈹  鈹斺敩鈹樷攤  鈹  鈹溾敜   鈹  鈹溾攢鈹も攤  鈹  鈹溾敶鈹愨敎鈹€鈹も攤  鈹溾敶鈹
  135.   //  鈺 鈺┾暕 鈺┾暆鈺氣暆鈺愨暕鈺濃暕鈺愨暆鈺氣晲鈺        鈹粹攢鈹樷敶鈹  鈹斺攢鈹樷敂鈹€鈹 鈹 鈹斺攢鈹樷敶鈹€鈹樷敂鈹€鈹  鈹斺攢鈹樷敶 鈹粹敶鈹€鈹樷敶鈹€鈹樷敂鈹€鈹樷敶 鈹粹敂鈹€鈹樷敶 鈹
  136.   // Determine what to do about running any lifecycle callback.
  137.   (function _runBeforeLC(proceed) {
  138.     // If the `skipAllLifecycleCallbacks` meta flag was set, don't run the lifecycle callback.
  139.     if (_.has(query.meta, 'skipAllLifecycleCallbacks') && query.meta.skipAllLifecycleCallbacks) {
  140.       return proceed(undefined, query);
  141.     }
  142.  
  143.     // If there is no relevant LC, then just proceed.
  144.     if (!_.has(WLModel._callbacks, 'beforeDestroy')) {
  145.       return proceed(undefined, query);
  146.     }
  147.  
  148.     // But otherwise, run it.
  149.     WLModel._callbacks.beforeDestroy(query.criteria, function (err){
  150.       if (err) { return proceed(err); }
  151.       return proceed(undefined, query);
  152.     });
  153.  
  154.   })(function _afterRunningBeforeLC(err, query) {
  155.     if (err) {
  156.       return done(err);
  157.     }
  158.  
  159.     var adapter = WLModel._adapter;
  160.  
  161.     //  鈹  鈹屸攢鈹愨攲鈹€鈹愨敩鈹屸攢鈹 鈹攲鈹€鈹  鈹屸攢鈹愨攲鈹攼鈹屸攢鈹愨攲鈹€鈹愨攲鈹攼鈹屸攢鈹愨敩鈹€鈹
  162.     //  鈹  鈹 鈹傗攤 鈹傗敎鈹粹攼鈹 鈹傗敎鈹€鈹  鈹溾攢鈹 鈹傗攤鈹溾攢鈹も敎鈹€鈹 鈹 鈹溾敜 鈹溾敩鈹
  163.     //  鈹粹攢鈹樷敂鈹€鈹樷敂鈹€鈹樷敶 鈹粹敂鈹€鈹樷敶    鈹 鈹粹攢鈹粹敇鈹 鈹粹敶   鈹 鈹斺攢鈹樷敶鈹斺攢
  164.     // Look up the appropriate adapter to use for this model.
  165.  
  166.     // Verify the adapter has a `destroy` method.
  167.     if (!adapter.destroy) {
  168.       return done(new Error('Cannot complete query: The adapter used by this model (`' + modelIdentity + '`) doesn\'t support the `destroy` method.'));
  169.     }
  170.  
  171.     // If `cascade` or `fetch` is enabled, do a couple of extra assertions...
  172.     if (query.meta && (query.meta.cascade || query.meta.fetch)){
  173.  
  174.       // First, a sanity check to ensure the adapter has both `destroy` AND `find` methods.
  175.       if (!adapter.find) {
  176.         return done(new Error('Cannot complete query: The adapter used by this model (`' + modelIdentity + '`) doesn\'t support the `find` method, but that method is mandatory to be able to use `cascade: true` or `fetch: true`.'));
  177.       }
  178.  
  179.     }//>-
  180.  
  181.     // Get a reference to the adapter.
  182.     var adapter = WLModel._adapter;
  183.     if (!adapter) {
  184.       // ^^One last sanity check to make sure the adapter exists-- again, for compatibility's sake.
  185.       return done(new Error('Consistency violation: Cannot find adapter for model (`' + modelIdentity + '`).  This model appears to be using datastore `'+WLModel.datastore+'`, but the adapter for that datastore cannot be located.'));
  186.     }
  187.  
  188.  
  189.  
  190.     // ================================================================================
  191.     // FUTURE: potentially bring this back (but also would need the `omit clause`)
  192.     // ================================================================================
  193.     // // Before we get to forging again, save a copy of the stage 2 query's
  194.     // // `select` clause.  We'll need this later on when processing the resulting
  195.     // // records, and if we don't copy it now, it might be damaged by the forging.
  196.     // //
  197.     // // > Note that we don't need a deep clone.
  198.     // // > (That's because the `select` clause is only 1 level deep.)
  199.     // var s2QSelectClause = _.clone(query.criteria.select);
  200.     // ================================================================================
  201.  
  202.  
  203.     //  鈺斺晲鈺椻晹鈺愨晽鈺︹晲鈺椻晹鈺愨晽鈺斺晲鈺  鈹屸攢鈹愨攲鈹攼鈹屸攢鈹愨攲鈹€鈹愨攲鈹€鈹  鈹屸敩鈹愨敩 鈹敩鈹€鈹愨攲鈹€鈹愨攲鈹€鈹  鈹屸攢鈹 鈹 鈹攲鈹€鈹愨敩鈹€鈹愨敩 鈹
  204.     //  鈺犫暎 鈺 鈺戔暊鈺︹暆鈺 鈺︹晳鈺   鈹斺攢鈹 鈹 鈹溾攢鈹も攤 鈹敎鈹    鈹 鈹溾攢鈹も敎鈹敇鈹溾敜 鈹溾敜   鈹傗攢鈹尖攼鈹 鈹傗敎鈹 鈹溾敩鈹樷敂鈹敇
  205.     //  鈺  鈺氣晲鈺濃暕鈺氣晲鈺氣晲鈺濃暁鈺愨暆  鈹斺攢鈹 鈹 鈹 鈹粹敂鈹€鈹樷敂鈹€鈹   鈹 鈹 鈹粹敶鈹斺攢鈹斺攢鈹樷敂鈹€鈹  鈹斺攢鈹樷敂鈹斺攢鈹樷敂鈹€鈹樷敶鈹斺攢 鈹
  206.     // Now, destructively forge this S2Q into a S3Q.
  207.     try {
  208.       query = forgeStageThreeQuery({
  209.         stageTwoQuery: query,
  210.         identity: modelIdentity,
  211.         transformer: WLModel._transformer,
  212.         originalModels: orm.collections
  213.       });
  214.     } catch (e) { return done(e); }
  215.  
  216.  
  217.     //  鈹攲鈹€鈹  鈺斺晲鈺椻晹鈺愨晽鈺斺晲鈺椻晹鈺愨晽鈺斺晲鈺椻晹鈺︹晽鈺斺晲鈺  鈹屸攢鈹愨攲鈹愨攲鈹屸攢鈹愨攲鈹 鈹  鈹屸攢鈹愨攲鈹攼   鈹屸敩鈹愨敩 鈹攲鈹€鈹愨攲鈹愨攲
  218.     //  鈹傗敎鈹   鈺  鈺犫晲鈺b暁鈺愨晽鈺  鈺犫晲鈺 鈺戔晳鈺戔暎   鈹溾敜 鈹傗攤鈹傗敎鈹€鈹も敎鈹粹攼鈹  鈹溾敜  鈹傗攤    鈹 鈹溾攢鈹も敎鈹 鈹傗攤鈹
  219.     //  鈹粹敂    鈺氣晲鈺濃暕 鈺┾暁鈺愨暆鈺氣晲鈺濃暕 鈺┾晲鈺┾暆鈺氣晲鈺  鈹斺攢鈹樷敇鈹斺敇鈹 鈹粹敂鈹€鈹樷敶鈹€鈹樷敂鈹€鈹樷攢鈹粹敇鈹   鈹 鈹 鈹粹敂鈹€鈹樷敇鈹斺敇
  220.     //  鈹屸攢鈹愨敩鈹屸攼鈹屸攲鈹攼  鈺︹晹鈺︹晽鈺斺晲鈺  鈹屸敩鈹愨攲鈹€鈹  鈹屸敩鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹攼鈹攢鈹愨攲鈹€鈹愨敩 鈹
  221.     //  鈹溾敜 鈹傗攤鈹傗攤 鈹傗攤  鈺 鈺戔晳鈺氣晲鈺   鈹 鈹 鈹   鈹傗攤鈹溾敜 鈹斺攢鈹 鈹 鈹溾敩鈹樷攤 鈹傗敂鈹敇
  222.     //  鈹  鈹粹敇鈹斺敇鈹€鈹粹敇  鈺┾晲鈺┾暆鈺氣晲鈺   鈹 鈹斺攢鈹  鈹€鈹粹敇鈹斺攢鈹樷敂鈹€鈹 鈹 鈹粹敂鈹€鈹斺攢鈹 鈹
  223.     (function _maybeFindIdsToDestroy(proceed) {
  224.  
  225.       // If `cascade` meta key is NOT enabled, then just proceed.
  226.       if (!_.has(query.meta, 'cascade') || query.meta.cascade === false) {
  227.         return proceed();
  228.       }
  229.  
  230.       // Look up the ids of records that will be destroyed.
  231.       // (We need these because, later, since `cascade` is enabled, we'll need
  232.       // to empty out all of their associated collections.)
  233.       //
  234.       // > FUTURE: instead of doing this, consider forcing `fetch: true` in the
  235.       // > implementation of `.destroy()` when `cascade` meta key is enabled (mainly
  236.       // > for consistency w/ the approach used in createEach()/create())
  237.  
  238.       // To do this, we'll grab the appropriate adapter method and call it with a stage 3
  239.       // "find" query, using almost exactly the same QKs as in the incoming "destroy".
  240.       // The only tangible difference is that its criteria has a `select` clause so that
  241.       // records only contain the primary key field (by column name, of course.)
  242.       var pkColumnName = WLModel.schema[WLModel.primaryKey].columnName;
  243.  
  244.       if (!pkColumnName) {
  245.         return done(new Error('Consistency violation: model `' + WLModel.identity + '` schema has no primary key column name!'));
  246.       }
  247.  
  248.       adapter.find(WLModel.datastore, {
  249.         method: 'find',
  250.         using: query.using,
  251.         criteria: {
  252.           where: query.criteria.where,
  253.           skip: query.criteria.skip,
  254.           limit: query.criteria.limit,
  255.           sort: query.criteria.sort,
  256.           select: [ pkColumnName ]
  257.         },
  258.         meta: query.meta //<< this is how we know that the same db connection will be used
  259.       }, function _afterPotentiallyFindingIdsToDestroy(err, pRecords) {
  260.         if (err) {
  261.           return proceed(err);
  262.         }
  263.  
  264.         // Slurp out just the array of ids (pk values), and send that back.
  265.         var ids = _.pluck(pRecords, pkColumnName);
  266.         return proceed(undefined, ids);
  267.  
  268.       });//</adapter.find()>
  269.  
  270.     })(function _afterPotentiallyLookingUpRecordsToCascade(err, idsOfRecordsBeingDestroyedMaybe) {
  271.       if (err) { return done(err); }
  272.  
  273.  
  274.       // Now we'll actually perform the `destroy`.
  275.  
  276.       //  鈹屸攢鈹愨攲鈹€鈹愨攲鈹愨攲鈹屸敩鈹  鈹屸敩鈹愨攲鈹€鈹  鈺斺晲鈺椻晹鈺︹晽鈺斺晲鈺椻晹鈺愨晽鈺斺暒鈺椻晹鈺愨晽鈺︹晲鈺
  277.       //  鈹斺攢鈹愨敎鈹 鈹傗攤鈹 鈹傗攤   鈹 鈹 鈹  鈺犫晲鈺 鈺戔晳鈺犫晲鈺b暊鈺愨暆 鈺 鈺戔暎 鈺犫暒鈺
  278.       //  鈹斺攢鈹樷敂鈹€鈹樷敇鈹斺敇鈹€鈹粹敇   鈹 鈹斺攢鈹  鈺 鈺┾晲鈺┾暆鈺 鈺┾暕   鈺 鈺氣晲鈺濃暕鈺氣晲
  279.       // Call the `destroy` adapter method.
  280.       adapter.destroy(WLModel.datastore, query, function _afterTalkingToAdapter(err, rawAdapterResult) {
  281.         if (err) {
  282.           if (!_.isError(err)) {
  283.             return done(new Error(
  284.               'If an error is sent back from the adapter, it should always be an Error instance.  '+
  285.               'But instead, got: '+util.inspect(err, {depth:5})+''
  286.             ));
  287.           }//-鈥
  288.           // Attach the identity of this model (for convenience).
  289.           err.modelIdentity = modelIdentity;
  290.           return done(err);
  291.         }//-鈥
  292.  
  293.  
  294.         //  鈺︹晲鈺椻晹鈺愨晽鈺︹晹鈺椻晹  鈺斺暒鈺椻晹鈺愨晽鈺 鈺︹晹鈺椻晹  鈺斺暒鈺椻晹鈺愨晽鈺斺晲鈺椻晹鈺︹晽鈺︹晲鈺椻暒 鈺︹晹鈺愨晽鈺斺暒鈺椻暒鈺斺晲鈺椻晹鈺椻晹  鈹屸攢鈹愨攲鈹愨攲鈹屸敩鈹愨攲鈹€鈹
  295.         //  鈺犫暒鈺濃暊鈺愨暎鈺戔晳鈺戔晳   鈺戔晳鈺 鈺戔晳鈺戔晳鈺戔晳鈺   鈺戔晳鈺戔暎 鈺氣晲鈺 鈺 鈺犫暒鈺濃晳 鈺戔晳   鈺 鈺戔晳 鈺戔晳鈺戔晳  鈹 鈹傗攤鈹傗攤 鈹 鈹 鈹
  296.         //  鈺┾暁鈺愨暕 鈺┾暕鈺濃暁鈺  鈺愨暕鈺濃暁鈺愨暆鈺氣暕鈺濃暆鈺氣暆  鈺愨暕鈺濃暁鈺愨暆鈺氣晲鈺 鈺 鈺┾暁鈺愨暁鈺愨暆鈺氣晲鈺 鈺 鈺┾暁鈺愨暆鈺濃暁鈺  鈹斺攢鈹樷敇鈹斺敇 鈹 鈹斺攢鈹
  297.         //  鈹屸攢鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨敩鈹屸攢鈹愨攲鈹攼鈹攲鈹€鈹愨攲鈹愨攲鈹屸攢鈹  鈹屸攢  鈹 鈹屸攢鈹   鈹屸攢鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹攼鈹屸攢鈹  鈹€鈹
  298.         //  鈹溾攢鈹も敂鈹€鈹愨敂鈹€鈹愨攤 鈹傗攤  鈹傗敎鈹€鈹 鈹 鈹傗攤 鈹傗攤鈹傗攤鈹斺攢鈹  鈹   鈹 鈹溾敜    鈹  鈹溾攢鈹も敂鈹€鈹愨攤  鈹溾攢鈹 鈹傗攤鈹溾敜    鈹
  299.         //  鈹 鈹粹敂鈹€鈹樷敂鈹€鈹樷敂鈹€鈹樷敂鈹€鈹樷敶鈹 鈹 鈹 鈹粹敂鈹€鈹樷敇鈹斺敇鈹斺攢鈹  鈹斺攢  鈹磑鈹斺攢鈹榦  鈹斺攢鈹樷敶 鈹粹敂鈹€鈹樷敂鈹€鈹樷敶 鈹粹攢鈹粹敇鈹斺攢鈹  鈹€鈹
  300.         (function _maybeWipeAssociatedCollections(proceed) {
  301.  
  302.           // If `cascade` meta key is NOT enabled, then just proceed.
  303.           if (!_.has(query.meta, 'cascade') || query.meta.cascade === false) {
  304.             return proceed();
  305.           }
  306.  
  307.           // Otherwise, then we should have the records we looked up before.
  308.           // (Here we do a quick sanity check.)
  309.           if (!_.isArray(idsOfRecordsBeingDestroyedMaybe)) {
  310.             return proceed(new Error('Consistency violation: Should have an array of records looked up before!  But instead, got: '+util.inspect(idsOfRecordsBeingDestroyedMaybe, {depth: 5})+''));
  311.           }
  312.  
  313.           // --鈥
  314.           // Now we'll clear out collections belonging to the specified records.
  315.           // (i.e. use `replaceCollection` to wipe them all out to be `[]`)
  316.  
  317.  
  318.           // First, if there are no target records, then gracefully bail without complaint.
  319.           // (i.e. this is a no-op)
  320.           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  321.           // FUTURE: Revisit this and verify that it's unnecessary.  While this isn't a bad micro-optimization,
  322.           // its existence makes it seem like this wouldn't work or would cause a warning or something.  And it
  323.           // really shouldn't be necessary.  (It's doubtful that it adds any real tangible performance benefit anyway.)
  324.           // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  325.           if (idsOfRecordsBeingDestroyedMaybe.length === 0) {
  326.             return proceed();
  327.           }//-鈥
  328.  
  329.           // Otherwise, we have work to do.
  330.           //
  331.           // Run .replaceCollection() for each associated collection of the targets, wiping them all out.
  332.           // (if n..m, this destroys junction records; otherwise, it's n..1, so this just nulls out the other side)
  333.           //
  334.           // > Note that we pass through `meta` here, ensuring that the same db connection is used, if possible.
  335.           async.each(_.keys(WLModel.attributes), function _eachAttribute(attrName, next) {
  336.  
  337.             var attrDef = WLModel.attributes[attrName];
  338.  
  339.             // Skip everything other than collection attributes.
  340.             if (!attrDef.collection){ return next(); }
  341.  
  342.             // But otherwise, this is a collection attribute.  So wipe it.
  343.             WLModel.replaceCollection(idsOfRecordsBeingDestroyedMaybe, attrName, [], function (err) {
  344.               if (err) { return next(err); }
  345.  
  346.               return next();
  347.  
  348.             }, query.meta);//</.replaceCollection()>
  349.  
  350.           },// ~鈭?掳
  351.           function _afterwards(err) {
  352.             if (err) { return proceed(err); }
  353.  
  354.             return proceed();
  355.  
  356.           });//</ async.each >
  357.  
  358.         })(function _afterPotentiallyWipingCollections(err) {
  359.           if (err) {
  360.             return done(err);
  361.           }
  362.  
  363.           //  鈺斺暒鈺椻暒鈺愨晽鈺斺晲鈺椻晹鈺椻晹鈺斺晲鈺椻晹鈺愨晽鈺斺晲鈺椻暒鈺愨晽鈺斺暒鈺  鈹攢鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹€鈹愨敩鈹€鈹愨攲鈹攼鈹屸攢鈹   鈹屸攼 鈹 鈹攲鈹攼  鈹屸攢鈹愨攲鈹愨攲鈹 鈹 鈹  鈹攲鈹€鈹
  364.           //   鈺 鈺犫暒鈺濃暊鈺愨暎鈺戔晳鈺戔暁鈺愨晽鈺犫暎 鈺 鈺戔暊鈺︹暆鈺戔晳鈺  鈹溾敩鈹樷敎鈹 鈹  鈹 鈹傗敎鈹敇 鈹傗攤鈹斺攢鈹   鈹溾敶鈹愨攤 鈹 鈹   鈹 鈹傗攤鈹傗攤鈹 鈹斺敩鈹  鈹傗敎鈹
  365.           //   鈺 鈺┾暁鈺愨暕 鈺┾暆鈺氣暆鈺氣晲鈺濃暁  鈺氣晲鈺濃暕鈺氣晲鈺 鈺  鈹粹敂鈹€鈹斺攢鈹樷敂鈹€鈹樷敂鈹€鈹樷敶鈹斺攢鈹€鈹粹敇鈹斺攢鈹榦oo鈹斺攢鈹樷敂鈹€鈹 鈹   鈹斺攢鈹樷敇鈹斺敇鈹粹攢鈹樷敶   鈹粹敂
  366.           //  鈺斺晲鈺椻晹鈺愨晽鈺斺暒鈺椻晹鈺愨晽鈺 鈺  鈹屸敩鈹愨攲鈹€鈹愨攲鈹攼鈹屸攢鈹  鈹攲鈹€鈹屸攢鈹愨敩 鈹  鈹 鈹攲鈹€鈹愨攲鈹€鈹  鈹屸攢鈹愨攲鈹€鈹愨攲鈹攼  鈹屸敩鈹愨攲鈹€鈹  鈹屸敩鈹愨敩鈹€鈹愨敩 鈹攲鈹€鈹
  367.           //  鈺犫暎 鈺戔暎  鈺 鈺  鈺犫晲鈺  鈹傗攤鈹傗敎鈹  鈹 鈹溾攢鈹  鈹溾敶鈹愨敎鈹 鈹斺敩鈹  鈹傗攤鈹傗敎鈹€鈹も敂鈹€鈹  鈹斺攢鈹愨敎鈹  鈹    鈹 鈹 鈹   鈹 鈹溾敩鈹樷攤 鈹傗敎鈹
  368.           //  鈺  鈺氣晲鈺 鈺 鈺氣晲鈺濃暕 鈺  鈹 鈹粹敂鈹€鈹 鈹 鈹 鈹  鈹 鈹粹敂鈹€鈹 鈹   鈹斺敶鈹樷敶 鈹粹敂鈹€鈹  鈹斺攢鈹樷敂鈹€鈹 鈹    鈹 鈹斺攢鈹   鈹 鈹粹敂鈹€鈹斺攢鈹樷敂鈹€鈹
  369.           (function _maybeTransformRecords(proceed){
  370.  
  371.             // If `fetch` was not enabled, return.
  372.             if (!_.has(query.meta, 'fetch') || query.meta.fetch === false) {
  373.  
  374.               if (!_.isUndefined(rawAdapterResult) && _.isArray(rawAdapterResult)) {
  375.                 console.warn('\n'+
  376.                   'Warning: Unexpected behavior in database adapter:\n'+
  377.                   'Since `fetch` is NOT enabled, this adapter (for datastore `'+WLModel.datastore+'`)\n'+
  378.                   'should NOT have sent back anything as the 2nd argument when triggering the callback\n'+
  379.                   'from its `destroy` method.  But it did!  And since it\'s an array, displaying this\n'+
  380.                   'warning to help avoid confusion and draw attention to the bug.  Specifically, got:\n'+
  381.                   util.inspect(rawAdapterResult, {depth:5})+'\n'+
  382.                   '(Ignoring it and proceeding anyway...)'+'\n'
  383.                 );
  384.               }//>-
  385.  
  386.               // Continue on.
  387.               return proceed();
  388.  
  389.             }//-鈥
  390.  
  391.             // IWMIH then we know that `fetch: true` meta key was set, and so the
  392.             // adapter should have sent back an array.
  393.  
  394.             // Verify that the raw result from the adapter is an array.
  395.             if (!_.isArray(rawAdapterResult)) {
  396.               return proceed(new Error(
  397.                 'Unexpected behavior in database adapter: Since `fetch: true` was enabled, this adapter '+
  398.                 '(for datastore `'+WLModel.datastore+'`) should have sent back an array of records as the 2nd argument when triggering '+
  399.                 'the callback from its `destroy` method.  But instead, got: '+util.inspect(rawAdapterResult, {depth:5})+''
  400.               ));
  401.             }//-鈥
  402.  
  403.             // Attempt to convert the column names in each record back into attribute names.
  404.             var transformedRecords;
  405.             try {
  406.               transformedRecords = rawAdapterResult.map(function(record) {
  407.                 return WLModel._transformer.unserialize(record);
  408.               });
  409.             } catch (e) { return proceed(e); }
  410.  
  411.             // Check the records to verify compliance with the adapter spec,
  412.             // as well as any issues related to stale data that might not have been
  413.             // been migrated to keep up with the logical schema (`type`, etc. in
  414.             // attribute definitions).
  415.             try {
  416.               processAllRecords(transformedRecords, query.meta, modelIdentity, orm);
  417.             } catch (e) { return proceed(e); }
  418.  
  419.             // Now continue on.
  420.             return proceed(undefined, transformedRecords);
  421.  
  422.           })(function (err, transformedRecordsMaybe){
  423.             if (err) { return done(err); }
  424.  
  425.             //  鈺斺晲鈺椻晹鈺愨晽鈺斺暒鈺椻晹鈺愨晽鈺︹晲鈺  鈹屸敩鈹愨攲鈹€鈹愨攲鈹€鈹愨攲鈹攼鈹攢鈹愨攲鈹€鈹愨敩 鈹  鈹屸攢鈹愨攲鈹€鈹愨敩  鈹  鈹屸攼 鈹屸攢鈹愨攲鈹€鈹愨敩鈹屸攢
  426.             //  鈺犫晲鈺b暊鈺  鈺 鈺戔暎 鈺犫暒鈺   鈹傗攤鈹溾敜 鈹斺攢鈹 鈹 鈹溾敩鈹樷攤 鈹傗敂鈹敇  鈹  鈹溾攢鈹も攤  鈹  鈹溾敶鈹愨敎鈹€鈹も攤  鈹溾敶鈹
  427.             //  鈺 鈺┾暁   鈺 鈺氣晲鈺濃暕鈺氣晲  鈹€鈹粹敇鈹斺攢鈹樷敂鈹€鈹 鈹 鈹粹敂鈹€鈹斺攢鈹 鈹   鈹斺攢鈹樷敶 鈹粹敶鈹€鈹樷敶鈹€鈹樷敂鈹€鈹樷敶 鈹粹敂鈹€鈹樷敶 鈹
  428.             (function _runAfterLC(proceed) {
  429.  
  430.               // Run "after" lifecycle callback, if appropriate.
  431.               //
  432.               // Note that we skip it if any of the following are true:
  433.               // 鈥 `skipAllLifecycleCallbacks` flag is enabled
  434.               // 鈥 there IS no relevant lifecycle callback
  435.               var doRunAfterLC = (
  436.                 (!_.has(query.meta, 'skipAllLifecycleCallbacks') || query.meta.skipAllLifecycleCallbacks === false) &&
  437.                 _.has(WLModel._callbacks, 'afterDestroy')
  438.               );
  439.               if (!doRunAfterLC) {
  440.                 return proceed(undefined, transformedRecordsMaybe);
  441.               }
  442.  
  443.               // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  444.               // TODO: normalize this behavior (currently, it's kind of inconsistent vs update/destroy/create)
  445.               // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  446.               return WLModel._callbacks.afterDestroy(transformedRecordsMaybe, function(err) {
  447.                 if (err) { return proceed(err); }
  448.                 return proceed(undefined, transformedRecordsMaybe);
  449.               });
  450.  
  451.             })(function _afterRunningAfterLC(err, transformedRecordsMaybe) {
  452.               if (err) { return done(err); }
  453.  
  454.               return done(undefined, transformedRecordsMaybe);
  455.  
  456.             }); // </ after potentially running after LC >
  457.           });//</ after determining (and potentially transforming) the result from the adapter >
  458.         }); // </ _afterPotentiallyWipingCollections >
  459.       }); // </ adapter.destroy >
  460.     }); // </ afterPotentiallyLookingUpRecordsToCascade >
  461.   }); // </ _afterRunningBeforeLC >
  462. };
  463.  
downloaddestroy.js Source code - Download waterline Source code
Related Source Codes/Software:
notepad-plus-plus - Notepad++ official repository h... 2017-01-10
che - Eclipse Che: Next-generation Eclipse IDE. Open sou... 2017-01-10
Gource - oftware version control visualization ... 2017-01-10
FDFullscreenPopGesture - A UINavigationController's category to enable full... 2017-01-10
node-style-guide - A guide for styling your node.js / JavaScript code... 2017-01-09
Workerman - An asynchronous event driven PHP framework for eas... 2017-01-10
structor - An advanced visual editor for React components ... 2017-01-10
golearn - Machine Learning for Go 2017-01-10
poisontap - Exploits locked/password protected computers over ... 2017-01-10
kcptun - A Simple UDP Tunnel Based On KCP 2017-01-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top