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?
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> {
siblings(UserFriendsPivot.leftIDKey, UserFriendsPivot.rightIDKey)
}
// users who are friends with this user
var friendOf: Siblings<User, User, UserFriendsPivot> {
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