UNPKG

leancloud-storage

Version:
129 lines (111 loc) 3.73 kB
"use strict"; var _ = require('underscore'); module.exports = function (AV) { /** * Creates a new Relation for the given parent object and key. This * constructor should rarely be used directly, but rather created by * {@link AV.Object#relation}. * @param {AV.Object} parent The parent of this relation. * @param {String} key The key for this relation on the parent. * @see AV.Object#relation * @class * * <p> * A class that is used to access all of the children of a many-to-many * relationship. Each instance of AV.Relation is associated with a * particular parent object and key. * </p> */ AV.Relation = function (parent, key) { if (!_.isString(key)) { throw new TypeError('key must be a string'); } this.parent = parent; this.key = key; this.targetClassName = null; }; /** * Creates a query that can be used to query the parent objects in this relation. * @param {String} parentClass The parent class or name. * @param {String} relationKey The relation field key in parent. * @param {AV.Object} child The child object. * @return {AV.Query} */ AV.Relation.reverseQuery = function (parentClass, relationKey, child) { var query = new AV.Query(parentClass); query.equalTo(relationKey, child._toPointer()); return query; }; _.extend(AV.Relation.prototype, /** @lends AV.Relation.prototype */ { /** * Makes sure that this relation has the right parent and key. * @private */ _ensureParentAndKey: function _ensureParentAndKey(parent, key) { this.parent = this.parent || parent; this.key = this.key || key; if (this.parent !== parent) { throw new Error('Internal Error. Relation retrieved from two different Objects.'); } if (this.key !== key) { throw new Error('Internal Error. Relation retrieved from two different keys.'); } }, /** * Adds a AV.Object or an array of AV.Objects to the relation. * @param {AV.Object|AV.Object[]} objects The item or items to add. */ add: function add(objects) { if (!_.isArray(objects)) { objects = [objects]; } var change = new AV.Op.Relation(objects, []); this.parent.set(this.key, change); this.targetClassName = change._targetClassName; }, /** * Removes a AV.Object or an array of AV.Objects from this relation. * @param {AV.Object|AV.Object[]} objects The item or items to remove. */ remove: function remove(objects) { if (!_.isArray(objects)) { objects = [objects]; } var change = new AV.Op.Relation([], objects); this.parent.set(this.key, change); this.targetClassName = change._targetClassName; }, /** * Returns a JSON version of the object suitable for saving to disk. * @return {Object} */ toJSON: function toJSON() { return { __type: 'Relation', className: this.targetClassName }; }, /** * Returns a AV.Query that is limited to objects in this * relation. * @return {AV.Query} */ query: function query() { var targetClass; var query; if (!this.targetClassName) { targetClass = AV.Object._getSubclass(this.parent.className); query = new AV.Query(targetClass); query._defaultParams.redirectClassNameForKey = this.key; } else { targetClass = AV.Object._getSubclass(this.targetClassName); query = new AV.Query(targetClass); } query._addCondition('$relatedTo', 'object', this.parent._toPointer()); query._addCondition('$relatedTo', 'key', this.key); return query; } }); };