diff --git a/app/adapters/crate.js b/app/adapters/crate.js index 9328d6cc674..544514604bf 100644 --- a/app/adapters/crate.js +++ b/app/adapters/crate.js @@ -5,6 +5,15 @@ const BULK_REQUEST_GROUP_SIZE = 10; export default class CrateAdapter extends ApplicationAdapter { coalesceFindRequests = true; + findRecord(store, type, id, snapshot) { + let { include } = snapshot; + // This ensures `crate.versions` are always fetched from another request. + if (include === undefined) { + snapshot.include = 'keywords,categories,downloads'; + } + return super.findRecord(store, type, id, snapshot); + } + groupRecordsForFindMany(store, snapshots) { let result = []; for (let i = 0; i < snapshots.length; i += BULK_REQUEST_GROUP_SIZE) { diff --git a/app/models/crate.js b/app/models/crate.js index 201be75d20c..cc73c860eb9 100644 --- a/app/models/crate.js +++ b/app/models/crate.js @@ -130,8 +130,10 @@ export default class Crate extends Model { return [...(teams ?? []), ...(users ?? [])]; }); - loadVersionsTask = task(async () => { - return (await this.versions) ?? []; + loadVersionsTask = task(async ({ reload = false } = {}) => { + let versionsRef = this.hasMany('versions'); + let fut = reload === true ? versionsRef.reload() : versionsRef.load(); + return (await fut) ?? []; }); } diff --git a/app/routes/crate/dependencies.js b/app/routes/crate/dependencies.js index ec0a3b0c1f6..8ffa3c3aa8a 100644 --- a/app/routes/crate/dependencies.js +++ b/app/routes/crate/dependencies.js @@ -6,7 +6,7 @@ export default class VersionRoute extends Route { async model() { let crate = this.modelFor('crate'); - let versions = await crate.get('versions'); + let versions = await crate.loadVersionsTask.perform(); let { default_version } = crate; let version = versions.find(version => version.num === default_version) ?? versions.lastObject; diff --git a/app/routes/crate/range.js b/app/routes/crate/range.js index 666d35d2b3e..e33d511b7ee 100644 --- a/app/routes/crate/range.js +++ b/app/routes/crate/range.js @@ -15,7 +15,7 @@ export default class VersionRoute extends Route { let crate = this.modelFor('crate'); try { - let versions = await crate.hasMany('versions').load(); + let versions = await crate.loadVersionsTask.perform(); let allVersionNums = versions.map(it => it.num); let unyankedVersionNums = versions.filter(it => !it.yanked).map(it => it.num); diff --git a/app/routes/crate/version-dependencies.js b/app/routes/crate/version-dependencies.js index 9eb18fd4ec5..75068fd7af4 100644 --- a/app/routes/crate/version-dependencies.js +++ b/app/routes/crate/version-dependencies.js @@ -9,7 +9,7 @@ export default class VersionRoute extends Route { let versions; try { - versions = await crate.get('versions'); + versions = await crate.loadVersionsTask.perform(); } catch (error) { let title = `${crate.name}: Failed to load version data`; return this.router.replaceWith('catch-all', { transition, error, title, tryAgain: true }); diff --git a/app/routes/crate/version.js b/app/routes/crate/version.js index bc83718357c..683fbf8f3fd 100644 --- a/app/routes/crate/version.js +++ b/app/routes/crate/version.js @@ -16,7 +16,7 @@ export default class VersionRoute extends Route { let versions; try { - versions = await crate.get('versions'); + versions = await crate.loadVersionsTask.perform(); } catch (error) { let title = `${crate.name}: Failed to load version data`; return this.router.replaceWith('catch-all', { transition, error, title, tryAgain: true }); diff --git a/e2e/acceptance/crate-dependencies.spec.ts b/e2e/acceptance/crate-dependencies.spec.ts index aa126869b8f..eb020ffa03f 100644 --- a/e2e/acceptance/crate-dependencies.spec.ts +++ b/e2e/acceptance/crate-dependencies.spec.ts @@ -75,14 +75,6 @@ test.describe('Acceptance | crate dependencies page', { tag: '@acceptance' }, () server.get('/api/v1/crates/:crate_name/versions', {}, 500); }); - await ember.addHook(async owner => { - // Load `crate` and then explicitly unload the side-loaded `versions`. - let store = owner.lookup('service:store'); - let crateRecord = await store.findRecord('crate', 'foo'); - let versions = crateRecord.hasMany('versions').value(); - versions.forEach(record => record.unloadRecord()); - }); - await page.goto('/crates/foo/1.0.0/dependencies'); await expect(page).toHaveURL('/crates/foo/1.0.0/dependencies'); diff --git a/e2e/routes/crate/range.spec.ts b/e2e/routes/crate/range.spec.ts index 3d760404f46..82e1f518c5b 100644 --- a/e2e/routes/crate/range.spec.ts +++ b/e2e/routes/crate/range.spec.ts @@ -127,14 +127,6 @@ test.describe('Route | crate.range', { tag: '@routes' }, () => { server.get('/api/v1/crates/:crate_name/versions', {}, 500); }); - await ember.addHook(async owner => { - // Load `crate` and then explicitly unload the side-loaded `versions`. - let store = owner.lookup('service:store'); - let crateRecord = await store.findRecord('crate', 'foo'); - let versions = crateRecord.hasMany('versions').value(); - versions.forEach(record => record.unloadRecord()); - }); - await page.goto('/crates/foo/range/^3'); await expect(page).toHaveURL('/crates/foo/range/%5E3'); await expect(page.locator('[data-test-404-page]')).toBeVisible(); diff --git a/tests/acceptance/crate-dependencies-test.js b/tests/acceptance/crate-dependencies-test.js index 0abe94438b9..c009c89c223 100644 --- a/tests/acceptance/crate-dependencies-test.js +++ b/tests/acceptance/crate-dependencies-test.js @@ -78,12 +78,6 @@ module('Acceptance | crate dependencies page', function (hooks) { this.server.get('/api/v1/crates/:crate_name/versions', {}, 500); - // Load `crate` and then explicitly unload the side-loaded `versions`. - let store = this.owner.lookup('service:store'); - let crateRecord = await store.findRecord('crate', 'foo'); - let versions = crateRecord.hasMany('versions').value(); - versions.forEach(record => record.unloadRecord()); - await visit('/crates/foo/1.0.0/dependencies'); assert.strictEqual(currentURL(), '/crates/foo/1.0.0/dependencies'); assert.dom('[data-test-404-page]').exists(); diff --git a/tests/adapters/crate-test.js b/tests/adapters/crate-test.js index 0b4a6722f27..2dcf265ce20 100644 --- a/tests/adapters/crate-test.js +++ b/tests/adapters/crate-test.js @@ -22,4 +22,21 @@ module('Adapter | crate', function (hooks) { assert.strictEqual(foo?.name, 'foo'); assert.strictEqual(bar?.name, 'bar'); }); + + test('findRecord requests do not include versions by default', async function (assert) { + let _foo = this.server.create('crate', { name: 'foo' }); + let version = this.server.create('version', { crate: _foo }); + + let store = this.owner.lookup('service:store'); + + let foo = await store.findRecord('crate', 'foo'); + assert.strictEqual(foo?.name, 'foo'); + + // versions should not be loaded yet + let versionsRef = foo.hasMany('versions'); + assert.deepEqual(versionsRef.ids(), []); + + await versionsRef.load(); + assert.deepEqual(versionsRef.ids(), [version.id]); + }); }); diff --git a/tests/models/version-test.js b/tests/models/version-test.js index 92203fc2e2c..fb92b98ff6f 100644 --- a/tests/models/version-test.js +++ b/tests/models/version-test.js @@ -229,7 +229,7 @@ module('Model | Version', function (hooks) { this.server.create('version', { crate, num: '0.4.2' }); this.server.create('version', { crate, num: '0.4.3', yanked: true }); crateRecord = await this.store.findRecord('crate', crate.name, { reload: true }); - versions = (await crateRecord.loadVersionsTask.perform()).slice(); + versions = (await crateRecord.loadVersionsTask.perform({ reload: true })).slice(); assert.deepEqual( versions.map(it => ({ num: it.num, isHighestOfReleaseTrack: it.isHighestOfReleaseTrack })), diff --git a/tests/routes/crate/range-test.js b/tests/routes/crate/range-test.js index 61474b7ad07..421658a157b 100644 --- a/tests/routes/crate/range-test.js +++ b/tests/routes/crate/range-test.js @@ -119,12 +119,6 @@ module('Route | crate.range', function (hooks) { this.server.get('/api/v1/crates/:crate_name/versions', {}, 500); - // Load `crate` and then explicitly unload the side-loaded `versions`. - let store = this.owner.lookup('service:store'); - let crateRecord = await store.findRecord('crate', 'foo'); - let versions = crateRecord.hasMany('versions').value(); - versions.forEach(record => record.unloadRecord()); - await visit('/crates/foo/range/^3'); assert.strictEqual(currentURL(), '/crates/foo/range/%5E3'); assert.dom('[data-test-404-page]').exists();