UNPKG

6.94 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _slicedToArray2 = require('babel-runtime/helpers/slicedToArray');
8
9var _slicedToArray3 = _interopRequireDefault(_slicedToArray2);
10
11var _extends2 = require('babel-runtime/helpers/extends');
12
13var _extends3 = _interopRequireDefault(_extends2);
14
15var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
16
17var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
18
19var _createClass2 = require('babel-runtime/helpers/createClass');
20
21var _createClass3 = _interopRequireDefault(_createClass2);
22
23var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
24
25var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
26
27var _inherits2 = require('babel-runtime/helpers/inherits');
28
29var _inherits3 = _interopRequireDefault(_inherits2);
30
31var _lodash = require('lodash');
32
33var _lodash2 = _interopRequireDefault(_lodash);
34
35var _helpers = require('./helpers');
36
37var _helpers2 = _interopRequireDefault(_helpers);
38
39var _promise = require('./base/promise');
40
41var _promise2 = _interopRequireDefault(_promise);
42
43var _eager = require('./base/eager');
44
45var _eager2 = _interopRequireDefault(_eager);
46
47function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48
49// EagerRelation
50// ---------------
51var getAttributeUnique = function getAttributeUnique(models, attribute) {
52 return _lodash2.default.uniq(_lodash2.default.map(models, function (m) {
53 return m.get(attribute);
54 }));
55};
56
57// An `EagerRelation` object temporarily stores the models from an eager load,
58// and handles matching eager loaded objects with their parent(s). The
59// `tempModel` is only used to retrieve the value of the relation method, to
60// know the constraints for the eager query.
61
62var EagerRelation = function (_EagerBase) {
63 (0, _inherits3.default)(EagerRelation, _EagerBase);
64
65 function EagerRelation() {
66 (0, _classCallCheck3.default)(this, EagerRelation);
67 return (0, _possibleConstructorReturn3.default)(this, (EagerRelation.__proto__ || Object.getPrototypeOf(EagerRelation)).apply(this, arguments));
68 }
69
70 (0, _createClass3.default)(EagerRelation, [{
71 key: 'eagerFetch',
72
73
74 // Handles an eager loaded fetch, passing the name of the item we're fetching
75 // for, and any options needed for the current fetch.
76 value: function eagerFetch(relationName, handled, options) {
77 var _this2 = this;
78
79 var relatedData = handled.relatedData;
80
81 // skip eager loading for rows where the foreign key isn't set
82 if (relatedData.parentFk === null) return;
83
84 if (relatedData.type === 'morphTo') {
85 return this.morphToFetch(relationName, relatedData, options);
86 }
87
88 return handled.sync((0, _extends3.default)({}, options, { parentResponse: this.parentResponse })).select().tap(function (response) {
89 return _this2._eagerLoadHelper(response, relationName, handled, _lodash2.default.omit(options, 'parentResponse'));
90 });
91 }
92
93 // Special handler for the eager loaded morph-to relations, this handles the
94 // fact that there are several potential models that we need to be fetching
95 // against. pairing them up onto a single response for the eager loading.
96
97 }, {
98 key: 'morphToFetch',
99 value: function morphToFetch(relationName, relatedData, options) {
100 var _this3 = this;
101
102 var columnNames = relatedData.columnNames || [];
103 var morphName = relatedData.morphName;
104
105 var _columnNames = (0, _slicedToArray3.default)(columnNames, 2),
106 _columnNames$ = _columnNames[0],
107 typeColumn = _columnNames$ === undefined ? morphName + '_type' : _columnNames$,
108 _columnNames$2 = _columnNames[1],
109 idColumn = _columnNames$2 === undefined ? morphName + '_id' : _columnNames$2;
110
111 var parentsByType = _lodash2.default.groupBy(this.parent, function (model) {
112 return model.get(typeColumn);
113 });
114 var TargetByType = _lodash2.default.mapValues(parentsByType, function (parents, type) {
115 return _helpers2.default.morphCandidate(relatedData.candidates, type);
116 });
117
118 return _promise2.default.all(_lodash2.default.map(parentsByType, function (parents, type) {
119 var Target = TargetByType[type];
120 var idAttribute = _lodash2.default.result(Target.prototype, 'idAttribute');
121 var ids = getAttributeUnique(parents, idColumn);
122
123 return Target.query('whereIn', idAttribute, ids).sync(options).select().tap(function (response) {
124 var clone = relatedData.instance('morphTo', Target, { morphName: morphName, columnNames: columnNames, morphValue: type });
125 return _this3._eagerLoadHelper(response, relationName, { relatedData: clone }, options);
126 });
127 })).then(_lodash2.default.flatten);
128 }
129
130 // Handles the eager load for both the `morphTo` and regular cases.
131
132 }, {
133 key: '_eagerLoadHelper',
134 value: function _eagerLoadHelper(response, relationName, handled, options) {
135 var _this4 = this;
136
137 var relatedModels = this.pushModels(relationName, handled, response);
138 var relatedData = handled.relatedData;
139
140 return _promise2.default.try(function () {
141 // If there is a response, fetch additional nested eager relations, if any.
142 if (response.length > 0 && options.withRelated) {
143 var relatedModel = relatedData.createModel();
144
145 // If this is a `morphTo` relation, we need to do additional processing
146 // to ensure we don't try to load any relations that don't look to exist.
147 if (relatedData.type === 'morphTo') {
148 var withRelated = _this4._filterRelated(relatedModel, options);
149 if (withRelated.length === 0) return;
150 options = _lodash2.default.extend({}, options, { withRelated: withRelated });
151 }
152 return new EagerRelation(relatedModels, response, relatedModel).fetch(options).return(response);
153 }
154 }).tap(function () {
155 return _promise2.default.map(relatedModels, function (model) {
156 return model.triggerThen('fetched', model, model.attributes, options);
157 });
158 });
159 }
160
161 // Filters the `withRelated` on a `morphTo` relation, to ensure that only valid
162 // relations are attempted for loading.
163
164 }, {
165 key: '_filterRelated',
166 value: function _filterRelated(relatedModel, options) {
167
168 // By this point, all withRelated should be turned into a hash, so it should
169 // be fairly simple to process by splitting on the dots.
170 return _lodash2.default.reduce(options.withRelated, function (memo, val) {
171 for (var key in val) {
172 var seg = key.split('.')[0];
173 if (_lodash2.default.isFunction(relatedModel[seg])) memo.push(val);
174 }
175 return memo;
176 }, []);
177 }
178 }]);
179 return EagerRelation;
180}(_eager2.default);
181
182exports.default = EagerRelation;
\No newline at end of file