FIX: Ensure injections are skipped when rehydrating stale models (#17574)

This was causing an error when opening the experimental user menu for the second time in a session

Co-authored-by: Jarek Radosz <jradosz@gmail.com>
This commit is contained in:
David Taylor 2022-07-19 21:53:32 +01:00 committed by GitHub
parent a842b71a05
commit 2159637e4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 1 deletions

View File

@ -141,7 +141,13 @@ export default Service.extend({
hydrated.get("content").map((item) => {
let staleItem = stale.content.findBy(primaryKey, item.get(primaryKey));
if (staleItem) {
staleItem.setProperties(item);
for (const [key, value] of Object.entries(
Object.getOwnPropertyDescriptors(staleItem)
)) {
if (value.writable && value.enumerable) {
staleItem.set(key, value.value);
}
}
} else {
staleItem = item;
}

View File

@ -6,11 +6,32 @@ import TopicTrackingState from "discourse/models/topic-tracking-state";
import { buildResolver } from "discourse-common/resolver";
import { currentSettings } from "discourse/tests/helpers/site-settings";
import Site from "discourse/models/site";
import RestModel from "discourse/models/rest";
const CatAdapter = RestAdapter.extend({
primaryKey: "cat_id",
});
const CachedCatAdapter = RestAdapter.extend({
primaryKey: "cat_id",
cache: true,
apiNameFor() {
return "cat";
},
});
const CachedCat = RestModel.extend({
init(...args) {
// Simulate an implicit injection
Object.defineProperty(this, "injectedProperty", {
writable: false,
enumerable: true,
value: "hello world",
});
this._super(...args);
},
});
export default function (customLookup = () => {}) {
const resolver = buildResolver("discourse").create({
namespace: { modulePrefix: "discourse" },
@ -28,6 +49,11 @@ export default function (customLookup = () => {}) {
this._catAdapter || CatAdapter.create({ owner: this });
return this._catAdapter;
}
if (type === "adapter:cached-cat") {
this._cachedCatAdapter =
this._cachedCatAdapter || CachedCatAdapter.create({ owner: this });
return this._cachedCatAdapter;
}
if (type === "adapter:rest") {
if (!this._restAdapter) {
this._restAdapter = RestAdapter.create({ owner: this });
@ -56,6 +82,9 @@ export default function (customLookup = () => {}) {
lookupFactory(type) {
const split = type.split(":");
if (type === "model:cached-cat") {
return CachedCat;
}
return resolver.resolveOther({
type: split[0],
fullNameWithoutType: split[1],

View File

@ -96,6 +96,19 @@ module("Unit | Service | store", function () {
);
});
test("rehydrating stale results with implicit injections", async function (assert) {
const store = createStore();
const cat = (await store.find("cached-cat", { name: "souna" })).content[0];
assert.strictEqual(cat.name, "souna");
const stale = store.findStale("cached-cat", { name: "souna" });
const refreshed = await stale.refresh();
assert.strictEqual(refreshed.content[0].name, "souna");
});
test("update", async function (assert) {
const store = createStore();
const result = await store.update("widget", 123, { name: "hello" });