mirror of
https://github.com/discourse/discourse.git
synced 2025-03-07 11:49:47 +00:00
Fix an issue with the store hydrating embedded objects
This commit is contained in:
parent
f600ead587
commit
b2ab95f9c2
app/assets/javascripts/discourse/models
test/javascripts
@ -8,6 +8,32 @@ function flushMap() {
|
|||||||
_identityMap = {};
|
_identityMap = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function storeMap(type, id, obj) {
|
||||||
|
if (!id) { return; }
|
||||||
|
|
||||||
|
_identityMap[type] = _identityMap[type] || {};
|
||||||
|
_identityMap[type][id] = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fromMap(type, id) {
|
||||||
|
const byType = _identityMap[type];
|
||||||
|
if (byType) { return byType[id]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeMap(type, id) {
|
||||||
|
const byType = _identityMap[type];
|
||||||
|
if (byType) { delete byType[id]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function findAndRemoveMap(type, id) {
|
||||||
|
const byType = _identityMap[type];
|
||||||
|
if (byType) {
|
||||||
|
const result = byType[id];
|
||||||
|
delete byType[id];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
flushMap();
|
flushMap();
|
||||||
|
|
||||||
export default Ember.Object.extend({
|
export default Ember.Object.extend({
|
||||||
@ -63,9 +89,8 @@ export default Ember.Object.extend({
|
|||||||
update(type, id, attrs) {
|
update(type, id, attrs) {
|
||||||
return this.adapterFor(type).update(this, type, id, attrs, function(result) {
|
return this.adapterFor(type).update(this, type, id, attrs, function(result) {
|
||||||
if (result && result[type] && result[type].id) {
|
if (result && result[type] && result[type].id) {
|
||||||
const oldRecord = _identityMap[type][id];
|
const oldRecord = findAndRemoveMap(type, id);
|
||||||
delete _identityMap[type][id];
|
storeMap(type, result[type].id, oldRecord);
|
||||||
_identityMap[type][result[type].id] = oldRecord;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
@ -78,8 +103,7 @@ export default Ember.Object.extend({
|
|||||||
|
|
||||||
destroyRecord(type, record) {
|
destroyRecord(type, record) {
|
||||||
return this.adapterFor(type).destroyRecord(this, type, record).then(function(result) {
|
return this.adapterFor(type).destroyRecord(this, type, record).then(function(result) {
|
||||||
const forType = _identityMap[type];
|
removeMap(type, record.get('id'));
|
||||||
if (forType) { delete forType[record.get('id')]; }
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -101,9 +125,7 @@ export default Ember.Object.extend({
|
|||||||
const klass = this.container.lookupFactory('model:' + type) || RestModel;
|
const klass = this.container.lookupFactory('model:' + type) || RestModel;
|
||||||
const model = klass.create(obj);
|
const model = klass.create(obj);
|
||||||
|
|
||||||
if (obj.id) {
|
storeMap(type, obj.id, model);
|
||||||
_identityMap[type][obj.id] = model;
|
|
||||||
}
|
|
||||||
return model;
|
return model;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -118,11 +140,24 @@ export default Ember.Object.extend({
|
|||||||
return Discourse.Category.findById(id);
|
return Discourse.Category.findById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pluralType = this.pluralize(subType);
|
||||||
const collection = root[this.pluralize(subType)];
|
const collection = root[this.pluralize(subType)];
|
||||||
if (collection) {
|
if (collection) {
|
||||||
const found = collection.findProperty('id', id);
|
const hashedProp = "__hashed_" + pluralType;
|
||||||
|
let hashedCollection = root[hashedProp];
|
||||||
|
if (!hashedCollection) {
|
||||||
|
hashedCollection = {};
|
||||||
|
collection.forEach(function(it) {
|
||||||
|
hashedCollection[it.id] = it;
|
||||||
|
});
|
||||||
|
root[hashedProp] = hashedCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
const found = hashedCollection[id];
|
||||||
if (found) {
|
if (found) {
|
||||||
return this._hydrate(subType, found, root);
|
const hydrated = this._hydrate(subType, found, root);
|
||||||
|
hashedCollection[id] = hydrated;
|
||||||
|
return hydrated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -154,9 +189,7 @@ export default Ember.Object.extend({
|
|||||||
this._hydrateEmbedded(obj, root);
|
this._hydrateEmbedded(obj, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
_identityMap[type] = _identityMap[type] || {};
|
const existing = fromMap(type, obj.id);
|
||||||
|
|
||||||
const existing = _identityMap[type][obj.id];
|
|
||||||
if (existing === obj) { return existing; }
|
if (existing === obj) { return existing; }
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
|
@ -39,6 +39,13 @@ const _moreWidgets = [
|
|||||||
{id: 224, name: 'Good Repellant'}
|
{id: 224, name: 'Good Repellant'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const fruits = [{id: 1, name: 'apple', farmer_id: 1, category_id: 4},
|
||||||
|
{id: 2, name: 'banana', farmer_id: 1, category_id: 3},
|
||||||
|
{id: 3, name: 'grape', farmer_id: 2, category_id: 5}];
|
||||||
|
|
||||||
|
const farmers = [{id: 1, name: 'Old MacDonald'},
|
||||||
|
{id: 2, name: 'Luke Skywalker'}];
|
||||||
|
|
||||||
function loggedIn() {
|
function loggedIn() {
|
||||||
return !!Discourse.User.current();
|
return !!Discourse.User.current();
|
||||||
}
|
}
|
||||||
@ -178,11 +185,13 @@ export default function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.get('/fruits/:id', function() {
|
this.get('/fruits/:id', function() {
|
||||||
return response({
|
const fruit = fruits[0];
|
||||||
__rest_serializer: "1",
|
|
||||||
fruit: {id: 1, name: 'apple', farmer_id: 1},
|
return response({ __rest_serializer: "1", fruit, farmers: [farmers[0]] });
|
||||||
farmers: [{id: 1, name: 'Evil Trout'}]
|
});
|
||||||
});
|
|
||||||
|
this.get('/fruits', function() {
|
||||||
|
return response({ __rest_serializer: "1", fruits, farmers });
|
||||||
});
|
});
|
||||||
|
|
||||||
this.get('/widgets/:widget_id', function(request) {
|
this.get('/widgets/:widget_id', function(request) {
|
||||||
|
@ -93,6 +93,15 @@ test('find embedded', function() {
|
|||||||
const store = createStore();
|
const store = createStore();
|
||||||
store.find('fruit', 1).then(function(f) {
|
store.find('fruit', 1).then(function(f) {
|
||||||
ok(f.get('farmer'), 'it has the embedded object');
|
ok(f.get('farmer'), 'it has the embedded object');
|
||||||
|
ok(f.get('category'), 'categories are found automatically');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('findAll embedded', function() {
|
||||||
|
const store = createStore();
|
||||||
|
store.findAll('fruit').then(function(fruits) {
|
||||||
|
equal(fruits.objectAt(0).get('farmer.name'), 'Old MacDonald');
|
||||||
|
equal(fruits.objectAt(0).get('farmer'), fruits.objectAt(1).get('farmer'), 'points at the same object');
|
||||||
|
equal(fruits.objectAt(2).get('farmer.name'), 'Luke Skywalker');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user