ember-data-model-fragments 4.0.0 → 5.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/addon/fragment.js CHANGED
@@ -110,16 +110,16 @@ const Fragment = Model.extend(Ember.Comparable, Copyable, {
110
110
  },
111
111
 
112
112
  /**
113
- @method _adapterDidCommit
113
+ @method _didCommit
114
114
  */
115
- _adapterDidCommit(data) {
115
+ _didCommit(data) {
116
116
  internalModelFor(this).adapterDidCommit({
117
117
  attributes: data || Object.create(null)
118
118
  });
119
119
  },
120
120
 
121
121
  /**
122
- @method _adapterDidCommit
122
+ @method _didCommit
123
123
  */
124
124
  _adapterDidError() {
125
125
  internalModelFor(this)._recordData.commitWasRejected();
@@ -127,7 +127,7 @@ const Fragment = Model.extend(Ember.Comparable, Copyable, {
127
127
 
128
128
  toStringExtension() {
129
129
  let internalModel = internalModelFor(this);
130
- let owner = internalModel && internalModel._recordData.getOwner();
130
+ let owner = internalModel && internalModel._recordData._owner;
131
131
  if (owner) {
132
132
  let ownerId = get(owner, 'id');
133
133
  return `owner(${ownerId})`;
@@ -179,10 +179,10 @@ export function internalModelFor(record) {
179
179
  export function setFragmentOwner(fragment, record, key) {
180
180
  let internalModel = internalModelFor(fragment);
181
181
 
182
- assert('To preserve rollback semantics, fragments can only belong to one owner. Try copying instead', !internalModel._recordData.getOwner() || internalModel._recordData.getOwner() === record);
182
+ assert('To preserve rollback semantics, fragments can only belong to one owner. Try copying instead', !internalModel._recordData._owner || internalModel._recordData._owner === record);
183
183
 
184
- internalModel._recordData.setOwner(record);
185
- internalModel._recordData.setName(key);
184
+ internalModel._recordData._owner = record;
185
+ internalModel._recordData._name = key;
186
186
 
187
187
  // Notify any observers of `fragmentOwner` properties
188
188
  get(fragment.constructor, 'fragmentOwnerProperties').forEach(name => {
@@ -0,0 +1,531 @@
1
+ // eslint-disable-next-line ember/use-ember-data-rfc-395-imports
2
+ import { RecordData } from 'ember-data/-private';
3
+ import { assert } from '@ember/debug';
4
+ import { typeOf } from '@ember/utils';
5
+ import { setProperties, get } from '@ember/object';
6
+ import { copy } from 'ember-copy';
7
+ import isInstanceOfType from './util/instance-of-type';
8
+ import { isArray } from '@ember/array';
9
+ import { fragmentDidDirty, fragmentDidReset } from './states';
10
+ import StatefulArray from './array/stateful';
11
+ import FragmentArray from './array/fragment';
12
+ import {
13
+ setFragmentOwner,
14
+ createFragment,
15
+ isFragment
16
+ } from './fragment';
17
+ import { assign } from '@ember/polyfills';
18
+ import { gte } from 'ember-compatibility-helpers';
19
+
20
+ let fragmentRecordDatas = new WeakMap();
21
+
22
+ export default class FragmentRecordData extends RecordData {
23
+ constructor(identifier, store) {
24
+ if (gte('ember-data', '3.15.0')) {
25
+ super(identifier, store);
26
+ } else {
27
+ super(identifier.type, identifier.id, identifier.clientId, store);
28
+ }
29
+
30
+ // @patocallaghan - We need to keep a copy of the record so we can recreate the fragment/fragmentArray.
31
+ this._record = null;
32
+ this.fragmentData = Object.create(null);
33
+ this.serverFragments = Object.create(null);
34
+ this.inFlightFragments = Object.create(null);
35
+
36
+ this.fragments = Object.create(null);
37
+ // @patocallaghan - We need to keep the fragment definitions for later on in case we need recreate the fragment or fragmentArray
38
+ this.fragmentDefs = Object.create(null);
39
+ let defs = store.attributesDefinitionFor(identifier.type, identifier.id, identifier.lid);
40
+
41
+ Object.keys(defs).forEach(key => {
42
+ let options = defs[key];
43
+ if (options.isFragment) {
44
+ this.fragmentDefs[key] = defs[key];
45
+ }
46
+ });
47
+ fragmentRecordDatas.set(identifier, this);
48
+ }
49
+
50
+ // Returns the value of the property or the default propery
51
+ getFragmentDataWithDefault(key, options, type) {
52
+ let data = this.fragmentData[key];
53
+ if (data !== undefined) {
54
+ return data;
55
+ }
56
+ return getFragmentDefaultValue(options, type);
57
+ }
58
+
59
+ setupFragment(key, options, declaredModelName, record) {
60
+ // @patocallaghan - This is extremely janky way of making sure we always have a copy of the record saved. There must be a better way of doing this?
61
+ this._record = record;
62
+ let data = this.getFragmentDataWithDefault(key, options, 'object');
63
+ let fragment = this.fragments[key];
64
+
65
+ if (!data) {
66
+ this.serverFragments[key] = data;
67
+ return data;
68
+ }
69
+
70
+ if (!fragment) {
71
+ fragment = createFragment(
72
+ record.store,
73
+ declaredModelName,
74
+ record,
75
+ key,
76
+ options,
77
+ data
78
+ );
79
+
80
+ this.serverFragments[key] = fragment;
81
+ }
82
+
83
+ return fragment;
84
+ }
85
+
86
+ getFragment(key, options, declaredModelName, record) {
87
+ this._record = record;
88
+ let fragment = this.getFragmentWithoutCreating(key);
89
+ if (fragment === undefined) {
90
+ return this.setupFragment(key, options, declaredModelName, record);
91
+ } else {
92
+ return fragment;
93
+ }
94
+ }
95
+
96
+ setFragmentArrayValue(key, fragments, value, record, declaredModelName, options, isFragmentArray) {
97
+ this._record = record;
98
+ if (isArray(value)) {
99
+ if (!fragments) {
100
+ if (isFragmentArray) {
101
+ fragments = FragmentArray.create({
102
+ type: declaredModelName,
103
+ options: options,
104
+ name: key,
105
+ owner: record
106
+ });
107
+ } else {
108
+ fragments = StatefulArray.create({
109
+ options: options,
110
+ name: key,
111
+ owner: record
112
+ });
113
+ }
114
+ }
115
+ fragments.setObjects(value);
116
+ } else if (value === null) {
117
+ fragments = null;
118
+ this.fragments[key] = null;
119
+ } else {
120
+ assert('A fragment array property can only be assigned an array or null');
121
+ }
122
+
123
+ if (this.serverFragments[key] !== fragments || get(fragments, 'hasDirtyAttributes')) {
124
+ fragmentDidDirty(record, key, fragments);
125
+ } else {
126
+ fragmentDidReset(record, key);
127
+ }
128
+
129
+ return fragments;
130
+ }
131
+
132
+ setFragmentValue(key, fragment, value, record, declaredModelName, options) {
133
+
134
+ // Model Fragments are hard tied to DS.Model, and all DS.Models have the store on them.
135
+ // We need access to the store because EDMF uses the store for `createRecord`
136
+ this._record = record;
137
+ let store = record.store;
138
+ assert(
139
+ `You can only assign \`null\`, an object literal or a '${declaredModelName}' fragment instance to this property`,
140
+ value === null ||
141
+ typeOf(value) === 'object' ||
142
+ isInstanceOfType(store.modelFor(declaredModelName), value)
143
+ );
144
+
145
+ if (!value) {
146
+ fragment = null;
147
+ } else if (isFragment(value)) {
148
+ // A fragment instance was given, so just replace the existing value
149
+ fragment = setFragmentOwner(value, record, key);
150
+ } else if (!fragment) {
151
+ // A property hash was given but the property was null, so create a new
152
+ // fragment with the data
153
+ fragment = createFragment(
154
+ store,
155
+ declaredModelName,
156
+ record,
157
+ key,
158
+ options,
159
+ value
160
+ );
161
+ } else {
162
+ // The fragment already exists and a property hash is given, so just set
163
+ // its values and let the state machine take care of the dirtiness
164
+ setProperties(fragment, value);
165
+
166
+ return fragment;
167
+ }
168
+
169
+ let currentFragment = this.getFragment(key, options, declaredModelName, record);
170
+
171
+ if (currentFragment !== fragment) {
172
+ this.fragments[key] = fragment;
173
+ fragmentDidDirty(record, key, fragment);
174
+ } else {
175
+ fragmentDidReset(record, key);
176
+ }
177
+ return fragment;
178
+ }
179
+
180
+ getFragmentArray(key, options, declaredModelName, record, isFragmentArray) {
181
+ this._record = record;
182
+ let data = this.getFragmentDataWithDefault(key, options, 'array');
183
+ let fragmentArray = this.getFragmentWithoutCreating(key);
184
+
185
+ // If we already have a processed fragment in _data and our current fragment is
186
+ // null simply reuse the one from data. We can be in this state after a rollback
187
+ // for example
188
+ if (fragmentArray === undefined) {
189
+ fragmentArray = this.setupFragmentArray(key, record, data, declaredModelName, options, isFragmentArray);
190
+ return fragmentArray;
191
+ } else {
192
+ return fragmentArray;
193
+ }
194
+ }
195
+
196
+ setupFragmentArray(key, record, data, declaredModelName, options, isFragmentArray) {
197
+ this._record = record;
198
+ let fragmentArray;
199
+ if (data !== null) {
200
+ if (isFragmentArray) {
201
+ fragmentArray = FragmentArray.create({
202
+ type: declaredModelName,
203
+ options: options,
204
+ name: key,
205
+ owner: record
206
+ });
207
+ } else {
208
+ fragmentArray = StatefulArray.create({
209
+ options: options,
210
+ name: key,
211
+ owner: record
212
+ });
213
+ }
214
+ fragmentArray.setupData(data);
215
+ } else {
216
+ fragmentArray = null;
217
+ }
218
+ this.serverFragments[key] = fragmentArray;
219
+ return fragmentArray;
220
+ }
221
+
222
+ getFragmentWithoutCreating(key) {
223
+ if (this.fragments[key] !== undefined) {
224
+ return this.fragments[key];
225
+ } else if (this.inFlightFragments[key] !== undefined) {
226
+ return this.inFlightFragments[key];
227
+ } else if (this.serverFragments[key] !== undefined) {
228
+ return this.serverFragments[key];
229
+ }
230
+ }
231
+ // PUBLIC API
232
+
233
+ setupFragmentData(data, calculateChange) {
234
+ let keys = [];
235
+ if (data.attributes) {
236
+ Object.keys(this.fragmentDefs).forEach(name => {
237
+ if (calculateChange && this.getFragmentWithoutCreating(name) !== undefined) {
238
+ keys.push(name);
239
+ }
240
+ if (name in data.attributes) {
241
+ this.fragmentData[name] = data.attributes[name];
242
+ let serverFragment = this.serverFragments[name];
243
+ if (serverFragment) {
244
+ let fragmentKeys = [];
245
+ if (data.attributes[name] === null) {
246
+ // if we have data with a Fragment set up, but now we've received null,
247
+ // delete the null fragment from serverFragments.
248
+ delete this.serverFragments[name];
249
+ } else if (serverFragment instanceof StatefulArray) {
250
+ serverFragment.setupData(data.attributes[name]);
251
+ } else {
252
+ fragmentKeys = serverFragment._internalModel._recordData.pushData({ attributes: data.attributes[name] }, calculateChange);
253
+ }
254
+ if (calculateChange) {
255
+ // TODO (Custom Model Classes) cleanup this api usage
256
+ fragmentKeys.forEach((fragmentKey) => serverFragment.notifyPropertyChange(fragmentKey));
257
+ }
258
+ } else if (serverFragment === null) {
259
+ // if we received data that set the fragment to null, but now we've received different data,
260
+ // delete the null fragment from serverFragments.
261
+ delete this.serverFragments[name];
262
+ }
263
+ }
264
+ });
265
+ }
266
+ return keys;
267
+ }
268
+
269
+ pushData(tempData, calculateChange) {
270
+ let data = tempData;
271
+
272
+ let ourAttributes = {};
273
+ if (data.attributes) {
274
+ Object.keys(this.fragmentDefs).forEach(name => {
275
+ if (name in data.attributes) {
276
+ ourAttributes[name] = data.attributes[name];
277
+ delete data.attributes[name];
278
+ }
279
+ });
280
+ }
281
+ let keys = this.setupFragmentData({ attributes: ourAttributes }, calculateChange);
282
+ let edKeys = super.pushData(data, calculateChange);
283
+ // TODO: for some reason, tempData is actually being modified. We need to merge
284
+ // the fragment data back in here so that it's not lost when we go back to the
285
+ // function calling pushData.
286
+ if (data.attributes) {
287
+ assign(data.attributes, ourAttributes);
288
+ }
289
+
290
+ return keys.concat(edKeys);
291
+ }
292
+
293
+ willCommit() {
294
+ let key, fragment;
295
+ for (key in this.fragments) {
296
+ fragment = this.fragments[key];
297
+ if (fragment) {
298
+ // TODO (Custom Model Classes) this bad, we should keep track of fragment record datas ourself
299
+ if (fragment.content) {
300
+ fragment.content.forEach(frag => {
301
+ // check to see if the array is a non-fragment array, if so, don't call
302
+ // method on _internalModel.recordData
303
+ // TODO: We need to add inFlight details to statefulArray, then change this.
304
+ if (frag._internalModel) {
305
+ frag._internalModel._recordData.willCommit();
306
+ }
307
+ });
308
+ } else {
309
+ fragment._internalModel._recordData.willCommit();
310
+ }
311
+ }
312
+ delete this.fragments[key];
313
+ this.inFlightFragments[key] = fragment;
314
+ }
315
+ super.willCommit();
316
+ }
317
+
318
+ hasChangedAttributes() {
319
+ return super.hasChangedAttributes() ||
320
+ Object.keys(this.fragmentDefs).some(fragmentName => {
321
+ const fragment = this.getFragmentWithoutCreating(fragmentName);
322
+ return fragment && fragment.hasDirtyAttributes;
323
+ });
324
+ }
325
+
326
+ resetRecord() {
327
+ super.resetRecord();
328
+ this.resetFragments();
329
+ }
330
+ resetFragments() {
331
+ let key, fragment;
332
+ for (key in this.fragments) {
333
+ fragment = this.fragments[key];
334
+ if (fragment) {
335
+ fragment.destroy();
336
+ delete this.fragments[key];
337
+ }
338
+ }
339
+
340
+ for (key in this.inFlightFragments) {
341
+ fragment = this.inFlightFragments[key];
342
+ if (fragment) {
343
+ fragment.destroy();
344
+ delete this.inFlightFragments[key];
345
+ }
346
+ }
347
+
348
+ for (key in this.serverFragments) {
349
+ fragment = this.serverFragments[key];
350
+ if (fragment) {
351
+ fragment.destroy();
352
+ delete this.serverFragments[key];
353
+ }
354
+ }
355
+ }
356
+
357
+ /*
358
+ Returns an object, whose keys are changed properties, and value is an
359
+ [oldProp, newProp] array.
360
+
361
+ @method changedAttributes
362
+ @private
363
+ */
364
+ changedAttributes() {
365
+ // NOTE: This is currently implemented in a very odd way in the case where the property on a fragment changes
366
+ // In that case, the expected return of changedAttributes is [ currentFragment, currentFragment ]
367
+ // This seems very broken, but might be a breaking change to fix.
368
+ // See the test named `changes to fragments are indicated in the owner record\'s `changedAttributes`
369
+ // for more details
370
+
371
+ let ourChanges = super.changedAttributes();
372
+ for (let key of Object.keys(this.fragmentDefs)) {
373
+ // either the whole fragment was replaced, or a property on the fragment was replaced
374
+ // this is the case where we replaced the whole framgent
375
+ let newFragment;
376
+ // We give priority to client set fragments in this.fragments but fall back to inFlight ones
377
+ // in case the record is already on the way
378
+ if (this.inFlightFragments[key] !== undefined) {
379
+ // TODD this code path isn't tested right now
380
+ newFragment = this.inFlightFragments[key];
381
+ }
382
+ if (this.fragments[key] !== undefined) {
383
+ newFragment = this.fragments[key];
384
+ }
385
+
386
+ if (newFragment !== undefined) {
387
+ // if we have a local fragment defined that means that we set that locally, so we need to diff against whatever was on the server
388
+ ourChanges[key] = [this.serverFragments[key], this.fragments[key]];
389
+ } else {
390
+ // this is the case where the fragment did not change but the props on it might have
391
+ // TODO diff against server
392
+ // otherwise we check to see if there are changes on the serverFragment and in that case the whole change is just the
393
+ // local change of that fragment
394
+ let fragment = this.serverFragments[key];
395
+
396
+ let hasChanged;
397
+ if (fragment && fragment instanceof StatefulArray) {
398
+ hasChanged = get(fragment, 'hasDirtyAttributes');
399
+ } else if (fragment) {
400
+ hasChanged = fragment._internalModel._recordData.hasChangedAttributes();
401
+ }
402
+
403
+ if (hasChanged) {
404
+ // NOTE: As explained above, this is very odd, and we should probably change it.
405
+ ourChanges[key] = [fragment, fragment];
406
+ }
407
+ }
408
+ }
409
+ return ourChanges;
410
+ }
411
+
412
+ rollbackAttributes() {
413
+ let keys = [];
414
+ for (let key in this.fragments) {
415
+ keys.push(key);
416
+ delete this.fragments[key];
417
+ }
418
+ Object.keys(this.fragmentDefs).forEach((key) => {
419
+ let fragment = this.getFragmentWithoutCreating(key);
420
+ if (fragment) {
421
+ fragment.rollbackAttributes();
422
+ keys.push(key);
423
+ }
424
+ });
425
+ return keys.concat(super.rollbackAttributes());
426
+ }
427
+
428
+ didCommit(data) {
429
+ let fragment, attributes;
430
+ if (data && data.attributes) {
431
+ attributes = data.attributes;
432
+ } else {
433
+ attributes = Object.create(null);
434
+ }
435
+ for (let key in this.inFlightFragments) {
436
+ fragment = this.inFlightFragments[key];
437
+ delete this.inFlightFragments[key];
438
+ this.serverFragments[key] = fragment;
439
+ }
440
+ Object.keys(this.fragmentDefs).forEach(key => {
441
+ fragment = this.serverFragments[key];
442
+ // @patocallaghan - So basically if the existing fragment/fragmentArray is null but it is part of the response we need to recreate the fragment/fragment array and re-add it to the record.
443
+ // Unfortunately we have no access to the `record` (is there a way to get it from `RecordData`?) in this codepath hence why we need to do the `this._record` hack.
444
+ if (!fragment && attributes[key] && this._record) {
445
+ let def = this.fragmentDefs[key];
446
+ let declaredModelName = def.type.split('$')[1];
447
+ if (def.type.includes('-array')) {
448
+ fragment = this.setupFragmentArray(key, this._record, attributes[key], declaredModelName, def.options, def.type.includes('fragment-array'));
449
+ } else {
450
+ fragment = createFragment(this._record.store, def.type.split('$')[1], this._record, key, def.options, attributes[key]);
451
+ }
452
+ // @patocallaghan - Not sure of the repercussions of just re-assigning the new fragment here. Should it be done a better way?
453
+ this._record[key] = fragment;
454
+ }
455
+ if (fragment) {
456
+ fragment._didCommit(attributes[key]);
457
+ }
458
+ delete attributes[key];
459
+ });
460
+ return super.didCommit(data);
461
+ }
462
+
463
+ commitWasRejected() {
464
+ let key, fragment;
465
+ for (key in this.inFlightFragments) {
466
+ fragment = this.inFlightFragments[key];
467
+ delete this.inFlightFragments[key];
468
+ if (this.fragments[key] === undefined) {
469
+ this.fragments[key] = fragment;
470
+ }
471
+ if (fragment) {
472
+ // TODO this bad, we should keep track of fragment record datas ourself
473
+ if (fragment.content) {
474
+ fragment.content.forEach(frag => {
475
+ // check to see if the array is a non-fragment array, if so, don't call
476
+ // method on _internalModel.recordData
477
+ // TODO: We need to add inFlight details to statefulArray, then change this.
478
+ if (frag._internalModel) {
479
+ frag._internalModel._recordData.commitWasRejected();
480
+ }
481
+ });
482
+ } else {
483
+ fragment._internalModel._recordData.commitWasRejected();
484
+ }
485
+ }
486
+ }
487
+ return super.commitWasRejected(...arguments);
488
+ }
489
+
490
+ setAttr(key, value) {
491
+ return super.setAttr(key, value);
492
+ }
493
+
494
+ getAttr(key) {
495
+ return super.getAttr(key);
496
+ }
497
+
498
+ hasAttr(key) {
499
+ return super.hasAttr(key);
500
+ }
501
+
502
+ didCreateLocally() {
503
+ return super.didCreateLocally();
504
+ }
505
+ }
506
+
507
+ export { fragmentRecordDatas };
508
+
509
+ // The default value of a fragment is either an array or an object,
510
+ // which should automatically get deep copied
511
+ function getFragmentDefaultValue(options, type) {
512
+ let value;
513
+
514
+ if (typeof options.defaultValue === 'function') {
515
+ return options.defaultValue();
516
+ } else if ('defaultValue' in options) {
517
+ value = options.defaultValue;
518
+ } else if (type === 'array') {
519
+ value = [];
520
+ } else {
521
+ return null;
522
+ }
523
+
524
+ assert(
525
+ `The fragment's default value must be an ${type}`,
526
+ typeOf(value) == type || value === null
527
+ );
528
+
529
+ // Create a deep copy of the resulting value to avoid shared reference errors
530
+ return copy(value, true);
531
+ }
package/addon/states.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { get } from '@ember/object';
2
+ // eslint-disable-next-line ember/use-ember-data-rfc-395-imports
2
3
  import { RootState } from 'ember-data/-private';
3
4
 
4
5
  /**
@@ -8,15 +9,15 @@ import { RootState } from 'ember-data/-private';
8
9
  const didSetProperty = RootState.loaded.saved.didSetProperty;
9
10
  const propertyWasReset = RootState.loaded.updated.uncommitted.propertyWasReset;
10
11
 
11
- function dirtySetup(internalModel) {
12
- const record = internalModel._recordData.getOwner();
13
- const key = internalModel._recordData.getName();
12
+ const dirtySetup = function(internalModel) {
13
+ let record = internalModel._recordData._owner;
14
+ let key = internalModel._recordData._name;
14
15
 
15
16
  // A newly created fragment may not have an owner yet
16
17
  if (record) {
17
18
  fragmentDidDirty(record, key, internalModel);
18
19
  }
19
- }
20
+ };
20
21
 
21
22
  /**
22
23
  Like `DS.Model` instances, all fragments have a `currentState` property
@@ -73,17 +74,20 @@ let FragmentRootState = {
73
74
  },
74
75
 
75
76
  loaded: {
77
+ unloadRecord() {
78
+ },
79
+
76
80
  pushedData(internalModel) {
77
81
  internalModel.transitionTo('saved');
78
82
  },
79
83
 
80
84
  saved: {
81
85
  setup(internalModel) {
82
- let record = internalModel._recordData.getOwner();
83
- let key = internalModel._recordData.getName();
86
+ let record = internalModel._recordData._owner;
87
+ let key = internalModel._recordData._name;
84
88
 
85
89
  // Abort if fragment is still initializing
86
- if (!record._internalModel._recordData.getFragment(key)) {
90
+ if (!record._internalModel._recordData.getFragmentWithoutCreating(key)) {
87
91
  return;
88
92
  }
89
93
 
@@ -101,6 +105,7 @@ let FragmentRootState = {
101
105
  becomeDirty(internalModel) {
102
106
  internalModel.transitionTo('updated');
103
107
  }
108
+
104
109
  },
105
110
 
106
111
  created: {
@@ -148,6 +153,7 @@ function wireState(object, parent, name) {
148
153
  object.stateName = name;
149
154
 
150
155
  for (let prop in object) {
156
+ // eslint-disable-next-line no-prototype-builtins
151
157
  if (!object.hasOwnProperty(prop) || prop === 'parentState' || prop === 'stateName') {
152
158
  continue;
153
159
  }
@@ -163,11 +169,8 @@ FragmentRootState = wireState(FragmentRootState, null, 'root');
163
169
 
164
170
  export default FragmentRootState;
165
171
 
166
- export function fragmentDidDirty(record, key, fragment) {
172
+ export function fragmentDidDirty(record) {
167
173
  if (!record.currentState.isDeleted) {
168
- // Add the fragment as a placeholder in the owner record's
169
- // `_attributes` hash to indicate it is dirty
170
- record._internalModel._recordData.setDirtyAttribute(key, fragment);
171
174
  record.send('becomeDirty');
172
175
  }
173
176
  }
@@ -175,7 +178,7 @@ export function fragmentDidDirty(record, key, fragment) {
175
178
  export function fragmentDidReset(record, key) {
176
179
  // Make sure there's no entry in the owner record's
177
180
  // `_attributes` hash to indicate the fragment is dirty
178
- delete record._internalModel._recordData._attributes[key];
181
+ // delete record._internalModel._attributes[key];
179
182
 
180
183
  // Don't reset if the record is new, otherwise it will enter the 'deleted' state
181
184
  // NOTE: This case almost never happens with attributes because their initial value
@@ -1,8 +1,9 @@
1
1
  import { assert } from '@ember/debug';
2
2
  import { getOwner } from '@ember/application';
3
3
  import { makeArray } from '@ember/array';
4
- import { get, computed } from '@ember/object';
5
- import Transform from 'ember-data/transform';
4
+ import { computed } from '@ember/object';
5
+ import Transform from '@ember-data/serializer/transform';
6
+ import { inject as service } from '@ember/service';
6
7
 
7
8
  /**
8
9
  @module ember-data-model-fragments
@@ -17,7 +18,7 @@ import Transform from 'ember-data/transform';
17
18
  @extends DS.Transform
18
19
  */
19
20
  const ArrayTransform = Transform.extend({
20
- store: null,
21
+ store: service(),
21
22
  type: null,
22
23
 
23
24
  deserialize: function deserializeArray(data) {
@@ -25,7 +26,7 @@ const ArrayTransform = Transform.extend({
25
26
  return null;
26
27
  }
27
28
 
28
- let transform = get(this, 'transform');
29
+ let transform = this.transform;
29
30
 
30
31
  data = makeArray(data);
31
32
 
@@ -41,7 +42,7 @@ const ArrayTransform = Transform.extend({
41
42
  return null;
42
43
  }
43
44
 
44
- let transform = get(this, 'transform');
45
+ let transform = this.transform;
45
46
 
46
47
  array = array.toArray ? array.toArray() : array;
47
48
 
@@ -53,7 +54,7 @@ const ArrayTransform = Transform.extend({
53
54
  },
54
55
 
55
56
  transform: computed('type', function() {
56
- let attributeType = this.get('type');
57
+ let attributeType = this.type;
57
58
 
58
59
  if (!attributeType) {
59
60
  return null;