Skip to content

Commit 16950b0

Browse files
authored
fix(pinia-orm): hasManyThrough doesn't work correctly with mulitple model instances
1 parent b1b8c27 commit 16950b0

File tree

2 files changed

+70
-2
lines changed

2 files changed

+70
-2
lines changed

packages/pinia-orm/src/model/attributes/relations/HasManyThrough.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class HasManyThrough extends Relation {
9595
const key = model[this.localKey]
9696

9797
dictionary[key]
98-
? model.$setRelation(relation, dictionary[key][0])
98+
? model.$setRelation(relation, dictionary[key].flat().filter(item => item !== undefined))
9999
: model.$setRelation(relation, [])
100100
})
101101
}

packages/pinia-orm/tests/feature/relations/has_many_through_retrieve.spec.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, expect, it } from 'vitest'
22

33
import { Model, useRepo } from '../../../src'
4-
import { Attr, HasManyThrough, Str } from '../../../src/decorators'
4+
import { Attr, HasMany, HasManyThrough, Str } from '../../../src/decorators'
55
import { assertInstanceOf, assertModel, fillState } from '../../helpers'
66

77
describe('feature/relations/has_many_through_retrieve', () => {
@@ -115,4 +115,72 @@ describe('feature/relations/has_many_through_retrieve', () => {
115115
expect(country.posts[0].id).toBe(2)
116116
expect(country.posts[1].id).toBe(1)
117117
})
118+
119+
it('can retrieve multi-level "has many through" relations with manual comparison', () => {
120+
// Extend the Country model with a direct relationship to users to manifest the difference
121+
class ExtendedCountry extends Country {
122+
@HasMany(() => User, 'countryId')
123+
declare users: User[]
124+
}
125+
126+
// Extend the User model with a direct relationship to posts to manifest the difference
127+
class ExtendedUser extends User {
128+
@HasMany(() => Post, 'userId')
129+
declare posts: Post[]
130+
}
131+
132+
const countryRepo = useRepo(ExtendedCountry)
133+
134+
// Set up test data with:
135+
// - 2 countries
136+
// - 3 users (2 in country 1, 1 in country 2)
137+
// - 5 posts (3 from user 1, 1 from user 2, 1 from user 3)
138+
fillState({
139+
users: {
140+
1: { id: 1, name: 'John Doe', countryId: 1 },
141+
2: { id: 2, name: 'Jane Doe', countryId: 1 },
142+
3: { id: 3, name: 'Johnny Doe', countryId: 2 },
143+
},
144+
countries: {
145+
1: { id: 1 },
146+
2: { id: 2 },
147+
},
148+
posts: {
149+
1: { id: 1, userId: 1, title: 'Title 01' },
150+
2: { id: 2, userId: 1, title: 'Title 02' },
151+
3: { id: 3, userId: 1, title: 'Title 03' },
152+
4: { id: 4, userId: 2, title: 'Title 04' },
153+
5: { id: 5, userId: 3, title: 'Title 05' },
154+
},
155+
})
156+
157+
// Register the extended user model to make posts accessible
158+
useRepo(ExtendedUser)
159+
160+
// Retrieve country with all related data
161+
const country = countryRepo.withAllRecursive().first()!
162+
163+
// Verify the country is retrieved correctly
164+
expect(country.id).toBe(1)
165+
166+
// Verify users are retrieved correctly
167+
expect(country.users.length).toBe(2)
168+
169+
// Verify posts are retrieved correctly through HasManyThrough
170+
expect(country.posts.length).toBe(4) // Should include all posts from all users in country 1
171+
172+
// Manually retrieve all posts through users to compare
173+
const manualPosts = country.users.flatMap((user) => {
174+
// Cast user to ExtendedUser to access posts
175+
return (user as unknown as ExtendedUser).posts
176+
})
177+
178+
// Compare the manual retrieval with the HasManyThrough relationship
179+
// This tests that HasManyThrough correctly retrieves all related models
180+
expect(country.posts.length).toEqual(manualPosts.length)
181+
182+
// Verify all expected post IDs are present
183+
const postIds = country.posts.map(post => post.id).sort()
184+
expect(postIds).toEqual([1, 2, 3, 4])
185+
})
118186
})

0 commit comments

Comments
 (0)