code: function replaceVirtualFields(options, model) {
  		if (options.attributes) {
  			for (var i = 0; i < options.attributes.length; i++) { // not using _.forEach as array is altered during looping
  				var fieldName = options.attributes[i],
  					field = model.attributes[fieldName];
  
  				if (!field) throw new Sequelize.VirtualFieldsError("Field '" + model.name + '.' + fieldName + "' referenced in a virtual field does not exist");
  
  				if (!(field.type instanceof Sequelize.VIRTUAL)) continue;
  
  				// field is virtual - add attributes & includes from virtualField
  				addVirtualFieldOptions(options, field, fieldName);
  
  				// delete virtual attribute
  				options.attributes.splice(i, 1);
  				i--;
  			}
  		} else {
  			// no attributes specified - all attributes of model will load so check all virtualFields
  			_.forIn(model.attributes, function(field, fieldName) {
  				// add attributes & includes from virtual field
  				if (field.type instanceof Sequelize.VIRTUAL) addVirtualFieldOptions(options, field, fieldName);
  			});
  		}
  
  		// repeat process for all includes recursively
  		var includes = options.include;
  		if (includes) {
  			_.forEach(includes, function(include, index) {
  				// if include given as model with no attributes/include, convert to {model: model} notation
  				if (patches.isModel(include)) include = includes[index] = {model: include};
  
  				// recurse through this include
  				replaceVirtualFields(include, include.model);
  			});
  		}
  	}
docs: ---------- functions