all files / lib/waterline/model/lib/internalMethods/ defineAssociations.js

100% Statements 41/41
90% Branches 9/10
100% Functions 9/9
100% Lines 38/38
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135                              2586×   2586×     2586×                 2586×           2586× 2586× 2586×   2586×     1495× 1080×       1495× 827×                       2586×     2586× 22152× 1080×     2586×                     2586×     2586× 22152× 827×     2586×                   1080×     1080×     1080× 285× 3881×                             827×     827×    
 
/**
 * Module dependencies
 */
 
var _ = require('lodash');
var Association = require('../association');
var utils = require('../../../utils/helpers');
var hasOwnProperty = utils.object.hasOwnProperty;
 
/**
 * Add association getters and setters for any has_many
 * attributes.
 *
 * @param {Object} context
 * @param {Object} proto
 * @api private
 */
 
var Define = module.exports = function(context, proto) {
  var self = this;
 
  this.proto = proto;
 
  // Build Associations Listing
  Object.defineProperty(proto, 'associations', {
    enumerable: false,
    writable: true,
    value: {}
  });
 
  // Build associations cache to hold original values.
  // Used to check if values have been mutated and need to be synced when
  // a model.save call is made.
  Object.defineProperty(proto, 'associationsCache', {
    enumerable: false,
    writable: true,
    value: {}
  });
 
  var attributes = context._attributes || {};
  var collections = this.collectionKeys(attributes);
  var models = this.modelKeys(attributes);
 
  if (collections.length === 0 && models.length === 0) return;
 
  // Create an Association getter and setter for each collection
  collections.forEach(function(collection) {
    self.buildHasManyProperty(collection);
  });
 
  // Attach Models to the prototype and set in the associations object
  models.forEach(function(model) {
    self.buildBelongsToProperty(model);
  });
};
 
/**
 * Find Collection Keys
 *
 * @param {Object} attributes
 * @api private
 * @return {Array}
 */
 
Define.prototype.collectionKeys = function(attributes) {
  var collections = [];
 
  // Find any collection keys
  for (var attribute in attributes) {
    if (!hasOwnProperty(attributes[attribute], 'collection')) continue;
    collections.push(_.cloneDeep(attribute));
  }
 
  return collections;
};
 
/**
 * Find Model Keys
 *
 * @param {Object} attributes
 * @api private
 * @return {Array}
 */
 
Define.prototype.modelKeys = function(attributes) {
  var models = [];
 
  // Find any collection keys
  for (var attribute in attributes) {
    if (!hasOwnProperty(attributes[attribute], 'model')) continue;
    models.push({ key: _.cloneDeep(attribute), val: _.cloneDeep(attributes[attribute]) });
  }
 
  return models;
};
 
/**
 * Create Getter/Setter for hasMany associations
 *
 * @param {String} collection
 * @api private
 */
 
Define.prototype.buildHasManyProperty = function(collection) {
  var self = this;
 
  // Attach to a non-enumerable property
  this.proto.associations[collection] = new Association();
 
  // Attach getter and setter to the model
  Object.defineProperty(this.proto, collection, {
    set: function(val) { self.proto.associations[collection]._setValue(val); },
    get: function() { return self.proto.associations[collection]._getValue(); },
    enumerable: true,
    configurable: true
  });
};
 
/**
 * Add belongsTo attributes to associations object
 *
 * @param {String} collection
 * @api private
 */
 
Define.prototype.buildBelongsToProperty = function(model) {
 
  // Attach to a non-enumerable property
  this.proto.associations[model.key] = model.val;
 
  // Build a cache for this model
  this.proto.associationsCache[model.key] = {};
};