mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 04:34:13 -06:00
FIX: Hydration of embedded records (#22809)
The store expects values for property names ending with `_id` to be a resource id and `_ids` to be an array of resource ids. This change ensures the store gracefully handles situations where an embedded field with incompliant data structure sneaks its way to production.
This commit is contained in:
parent
a8c504aee4
commit
4471eabd49
@ -6,6 +6,7 @@ import ResultSet from "discourse/models/result-set";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { getRegister } from "discourse-common/lib/get-owner";
|
||||
import { underscore } from "@ember/string";
|
||||
import { warn } from "@ember/debug";
|
||||
|
||||
let _identityMap;
|
||||
|
||||
@ -325,9 +326,18 @@ export default Service.extend({
|
||||
const subType = m[1];
|
||||
|
||||
if (m[2]) {
|
||||
if (!Array.isArray(obj[k])) {
|
||||
warn(`Expected an array of resource ids for ${type}.${k}`, {
|
||||
id: "discourse.store.hydrate-embedded",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const hydrated = obj[k].map((id) =>
|
||||
this._lookupSubType(subType, type, id, root)
|
||||
);
|
||||
|
||||
obj[this.pluralize(subType)] = hydrated || [];
|
||||
delete obj[k];
|
||||
} else {
|
||||
|
@ -12,7 +12,14 @@ const fruits = [
|
||||
{ id: 1, name: "apple", farmer_id: 1, color_ids: [1, 2], category_id: 4 },
|
||||
{ id: 2, name: "banana", farmer_id: 1, color_ids: [3], category_id: 3 },
|
||||
{ id: 3, name: "grape", farmer_id: 2, color_ids: [2], category_id: 5 },
|
||||
{ id: 4, name: "orange", farmer_id: null, color_ids: [2], category_id: 5 },
|
||||
{
|
||||
id: 4,
|
||||
name: "orange",
|
||||
farmer_id: null,
|
||||
color_ids: [2],
|
||||
category_id: 5,
|
||||
other_fruit_ids: { apple: 1, banana: 2 },
|
||||
},
|
||||
];
|
||||
|
||||
const farmers = [
|
||||
|
@ -263,4 +263,15 @@ module("Unit | Service | store", function (hooks) {
|
||||
assert.true(Array.isArray(result.topics));
|
||||
assert.strictEqual(result.filter, "topics/created-by/trout");
|
||||
});
|
||||
|
||||
test("Spec incompliant embedded record name", async function (assert) {
|
||||
const store = getOwner(this).lookup("service:store");
|
||||
const fruit = await store.find("fruit", 4);
|
||||
|
||||
assert.propContains(
|
||||
fruit.other_fruit_ids,
|
||||
{ apple: 1, banana: 2 },
|
||||
"embedded record remains unhydrated"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user