Skip to content

Commit

Permalink
Pass lid from relationship data to get record data
Browse files Browse the repository at this point in the history
The issue appeared in the sideposting scenario:

- model A has has many relationship to model B.

- instance of model A and instance of model B are created on the client,

- model A is saved along with model B sent in `include` section of
  payload; the linking is done through `lid`

- server persisted both models and sent the response with
  server-generated `id` along with `lid` sent by the client.

- when hasMany.updateData() was called while the response payload was
  pushed to the store it couldn't match the record which was already in
  the store with the record data contained in the relationship data
  because `lid` was omitted.

Add a test which ensures that the hasMany() relationship has correct
status in the sideposting with lid scenario.
  • Loading branch information
andreyfel committed Oct 7, 2020
1 parent 4bd2b32 commit 294186f
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { module, test } from 'qunit';
import { defer } from 'rsvp';
import { defer, resolve } from 'rsvp';

import { setupTest } from 'ember-qunit';

import Adapter from '@ember-data/adapter';
import { RECORD_DATA_STATE } from '@ember-data/canary-features';
import Model, { attr } from '@ember-data/model';
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
import Serializer from '@ember-data/serializer';
import Store, { recordIdentifierFor } from '@ember-data/store';

Expand Down Expand Up @@ -145,4 +145,79 @@ module('Integration | Identifiers - lid reflection', function(hooks) {

assert.strictEqual(record.name, '@runspired', 'After we finish we use the most recent clean name');
});

test('hasMany() has correct state after .save() on a newly created record with sideposted child record when lid is provided in the response payload', async function(assert) {
class Ingredient extends Model {
@attr name;
@belongsTo('cake') cake;
}

class Cake extends Model {
@attr name;
@hasMany('ingredient', { async: false }) ingredients;
}

this.owner.register('model:ingredient', Ingredient);
this.owner.register('model:cake', Cake);

class TestSerializer extends Serializer {
normalizeResponse(_, __, payload) {
return payload;
}
}
class TestAdapter extends Adapter {
createRecord(store, ModelClass, snapshot) {
return resolve({
data: {
type: 'cake',
id: '1',
attributes: {
name: 'Cheesecake',
},
relationships: {
ingredients: {
data: [
{
type: 'ingredient',
id: '2',
lid: cheeseIdentifier.lid,
},
],
},
},
},
included: [
{
type: 'ingredient',
id: '2',
lid: cheeseIdentifier.lid,
attributes: {
name: 'Cheese',
},
relationships: {
cake: {
data: {
type: 'cake',
id: '1',
},
},
},
},
],
});
}
}
this.owner.register('serializer:application', TestSerializer);
this.owner.register('adapter:application', TestAdapter);

const cheese = store.createRecord('ingredient', { name: 'Cheese' });
const cake = store.createRecord('cake', { name: 'Cheesecake', ingredients: [cheese] });

const cheeseIdentifier = recordIdentifierFor(cheese);

await cake.save();

assert.deepEqual(cake.hasMany('ingredients').ids(), ['2']);
assert.equal(cake.ingredients.objectAt(0).name, 'Cheese');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ export default class ManyRelationship extends Relationship {
} else {
recordDatas = new Array(data.length);
for (let i = 0; i < data.length; i++) {
recordDatas[i] = this.recordData.storeWrapper.recordDataFor(data[i].type, data[i].id) as RelationshipRecordData;
recordDatas[i] = this.recordData.storeWrapper.recordDataFor(
data[i].type,
data[i].id,
data[i].lid
) as RelationshipRecordData;
}
}
this.updateRecordDatasFromAdapter(recordDatas);
Expand Down

0 comments on commit 294186f

Please sign in to comment.