问题
I have a User
model which I want to add a friends
property to. Friends, are supposed to be other User
s.
I created the UserFriendsPivot
:
final class UserFriendsPivot: MySQLPivot, ModifiablePivot {
var id: Int?
var userID: User.ID
var friendID: User.ID
typealias Left = User
typealias Right = User
static var leftIDKey: WritableKeyPath<UserFriendsPivot, Int> {
return \.userID
}
static var rightIDKey: WritableKeyPath<UserFriendsPivot, Int> {
return \.friendID
}
init(_ user: User, _ friend: User) throws {
self.userID = try user .requireID()
self.friendID = try friend.requireID()
}
}
extension UserFriendsPivot: Migration {
public static var entity: String {
return "user_friends"
}
}
I added the friends
property to User
:
var friends: Siblings<User, User, UserFriendsPivot> {
return siblings()
}
Now, I'm seeing the following error on the line with return siblings()
:
Ambiguous use of 'siblings(related:through:)'
I tried to replace it with:
return siblings(related: User.self, through: UserFriendsPivot.self)
...without any luck.
I know that the two code snippets should work, because I straight-up copied them from another siblings relationship I built between Event
and User
that is working just fine.
The only difference I'm seeing is that I'm trying to build a relationship between the same models.
What can I do?
回答1:
Try replacing your friends
definition with something like:
var friends: Siblings<User,UserFriendsPivot.Right, UserFriendsPivot> {
return User.siblings()
}
EDIT:
It ought to work with Left
and Right
as the same table, but seems to fail because the aliases resolve to the base values. I.e. autocomplete in Xcode shows all the candidates for siblings
all end up being of type:
Siblings<User, User, UserFriendsPivot> siblings(...)
Instead of:
Siblings<User, UserFriendsPivot.Right, UserFriendsPivot> siblings(...)
and similar.
I'd suggest raising a bug on GitHub. In the meantime, how about creating a copy of User
with a different name and setting:
static let entity = "User"
to use the same physical table. Not pretty, but it might get you working.
回答2:
The issue here is that in a same-Model
(User-User
) siblings relation, Fluent cannot infer which sibling you are referring to – the sides need to be specified.
extension User {
// friends of this user
var friends: Siblings<User, User, UserFriendsPivot> {
return siblings(UserFriendsPivot.leftIDKey, UserFriendsPivot.rightIDKey)
}
// users who are friends with this user
var friendOf: Siblings<User, User, UserFriendsPivot> {
return siblings(UserFriendsPivot.rightIDKey, UserFriendsPivot.leftIDKey)
}
}
The other same-Model
consequence is that you will not be able to use the attach convenience method to add to the pivot table, and need to manually create instead:
let pivot = try UserFriendsPivot(user, friend)
pivot.save(on: req)
(There are other approaches to work around this, I just find these straightforward ways above the easiest to use. Specifying the sides and reversing the key positions to obtain the inverse relation are the important concepts.)
as answered by grundoon
来源:https://stackoverflow.com/questions/55201301/siblings-relationship-between-same-models-in-vapor