如何在基本类型和相关类型相同的 Vapor 3 中的 Fluent 模型上声明 Siblings 扩展?
How do I declare a Siblings extension on a Fluent model in Vapor 3 where the base and related types are the same?
我有一种数据类型,例如文件夹,文件夹可以任意嵌套在彼此之间 — 多对多关系。为了支持这一点,我构建了一个枢轴 table(我正在使用 MySQL)将 parent_folder_id
与 child_folder_id
相关联(folders
[= 上的外键37=]).在 Fluent 中,我将其建模为 FolderToSubfoldersPivot
,其方式与我的其他枢轴 类.
相同
我现在想使用 Siblings 扩展我的 Folder
类型以具有 subfolders
属性。代码如下:
extension Folder {
var subFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return siblings()
}
}
这类似于我为其他自定义类型编写 Siblings
类型的属性的方式,它们都有效。但是,对于这种情况 Xcode 给出以下错误:
Ambiguous use of 'siblings(related:through:)'
我认为这是因为 Siblings
的类型声明中 Folder
类型的两次使用。我已经尝试通过几种方式解决这个问题(类型别名,显式调用带参数的 siblings(related:through:)
方法等)无济于事。
如何让 siblings()
功能正常工作?还是我需要从头开始重新实现 Siblings struct 才能做我想做的事?
经过一段时间的摆弄,我找到了答案。
Fluent 的 siblings
便利功能的实现可以在 this highlighted segment on GitHub 中找到。为了讨论的清晰,我将其复制如下:
extension Model {
...
/// Free implementation where pivot constraints are met.
/// See `Model.siblings(_:_:)`.
public func siblings<Related, Through>(
related: Related.Type = Related.self,
through: Through.Type = Through.self
) -> Siblings<Self, Related, Through>
where Through.Right == Self, Through.Left == Related
{
return siblings(Through.rightIDKey, Through.leftIDKey)
}
/// Free implementation where pivot constraints are met.
/// See `Model.siblings(_:_:)`.
public func siblings<Related, Through>(
related: Related.Type = Related.self,
through: Through.Type = Through.self
) -> Siblings<Self, Related, Through>
where Through.Left == Self, Through.Right == Related
{
return siblings(Through.leftIDKey, Through.rightIDKey)
}
}
我认为问题是我想要的用法不明确。当 Self
是枢轴的 right-hand 类型并且 Related
是 left-hand 类型时,使用上面代码片段中的第一个函数。同理,反之则用第二个函数
由于我使用的是 Siblings<X, X, XPivot>
类型,Swift 无法确定哪个函数更好,因为每个函数都满足条件。
为了解决这个问题,我实现了自己的扩展:
extension Model {
public func childrenSiblings<Through>(
through: Through.Type = Through.self
) -> Siblings<Self, Self, Through>
where Through.Left == Self, Through.Right == Self
{
return siblings(Through.leftIDKey, Through.rightIDKey)
}
public func parentSiblings<Through>(
through: Through.Type = Through.self
) -> Siblings<Self, Self, Through>
where Through.Left == Self, Through.Right == Self
{
return siblings(Through.rightIDKey, Through.leftIDKey)
}
}
我用childrenSiblings
来表示你在寻找当前类型的children(也是同一类型),用parentSiblings
来寻找parents 当前类型(属于同一类型)。它们之间的区别在于对 siblings
的内部调用,其中 Through.leftIDKey
和 Through.rightIDKey
在第二个函数中切换。这是因为我如何构建枢轴 table(即 left-hand 列是 parent_folder_id
,right-hand 列是 child_folder_id
)。
这些函数的用法与常规siblings
函数的用法类似。在我的问题中,我将 Folder
类型与其他 Folder
s:
相关联
extension Folder {
var subFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return childrenSiblings()
}
var superFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return parentSiblings()
}
}
Pierce Darragh,您的自我回答非常好,使用 children
和 parent
标签完全符合个人偏好。另一种选择是简单地使 属性 名称与您对事物的思考方式保持一致(主要点仍然是关键位置的反转)。
例如,<User, User, FollowsPivot>
社交媒体类型关系可以表示为:
extension User {
var following: Siblings<User, User, FollowsPivot> {
return siblings(FollowsPivot.leftIDKey, FollowsPivot.rightIDKey)
}
var followers: Siblings<User, User, FollowsPivot> {
return siblings(FollowsPivot.rightIDKey, FollowsPivot.leftIDKey)
}
}
没有任何额外的扩展。我相信 siblings()
有 4 个变体,可以直接在 return
.
中使用
我有一种数据类型,例如文件夹,文件夹可以任意嵌套在彼此之间 — 多对多关系。为了支持这一点,我构建了一个枢轴 table(我正在使用 MySQL)将 parent_folder_id
与 child_folder_id
相关联(folders
[= 上的外键37=]).在 Fluent 中,我将其建模为 FolderToSubfoldersPivot
,其方式与我的其他枢轴 类.
我现在想使用 Siblings 扩展我的 Folder
类型以具有 subfolders
属性。代码如下:
extension Folder {
var subFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return siblings()
}
}
这类似于我为其他自定义类型编写 Siblings
类型的属性的方式,它们都有效。但是,对于这种情况 Xcode 给出以下错误:
Ambiguous use of 'siblings(related:through:)'
我认为这是因为 Siblings
的类型声明中 Folder
类型的两次使用。我已经尝试通过几种方式解决这个问题(类型别名,显式调用带参数的 siblings(related:through:)
方法等)无济于事。
如何让 siblings()
功能正常工作?还是我需要从头开始重新实现 Siblings struct 才能做我想做的事?
经过一段时间的摆弄,我找到了答案。
Fluent 的 siblings
便利功能的实现可以在 this highlighted segment on GitHub 中找到。为了讨论的清晰,我将其复制如下:
extension Model {
...
/// Free implementation where pivot constraints are met.
/// See `Model.siblings(_:_:)`.
public func siblings<Related, Through>(
related: Related.Type = Related.self,
through: Through.Type = Through.self
) -> Siblings<Self, Related, Through>
where Through.Right == Self, Through.Left == Related
{
return siblings(Through.rightIDKey, Through.leftIDKey)
}
/// Free implementation where pivot constraints are met.
/// See `Model.siblings(_:_:)`.
public func siblings<Related, Through>(
related: Related.Type = Related.self,
through: Through.Type = Through.self
) -> Siblings<Self, Related, Through>
where Through.Left == Self, Through.Right == Related
{
return siblings(Through.leftIDKey, Through.rightIDKey)
}
}
我认为问题是我想要的用法不明确。当 Self
是枢轴的 right-hand 类型并且 Related
是 left-hand 类型时,使用上面代码片段中的第一个函数。同理,反之则用第二个函数
由于我使用的是 Siblings<X, X, XPivot>
类型,Swift 无法确定哪个函数更好,因为每个函数都满足条件。
为了解决这个问题,我实现了自己的扩展:
extension Model {
public func childrenSiblings<Through>(
through: Through.Type = Through.self
) -> Siblings<Self, Self, Through>
where Through.Left == Self, Through.Right == Self
{
return siblings(Through.leftIDKey, Through.rightIDKey)
}
public func parentSiblings<Through>(
through: Through.Type = Through.self
) -> Siblings<Self, Self, Through>
where Through.Left == Self, Through.Right == Self
{
return siblings(Through.rightIDKey, Through.leftIDKey)
}
}
我用childrenSiblings
来表示你在寻找当前类型的children(也是同一类型),用parentSiblings
来寻找parents 当前类型(属于同一类型)。它们之间的区别在于对 siblings
的内部调用,其中 Through.leftIDKey
和 Through.rightIDKey
在第二个函数中切换。这是因为我如何构建枢轴 table(即 left-hand 列是 parent_folder_id
,right-hand 列是 child_folder_id
)。
这些函数的用法与常规siblings
函数的用法类似。在我的问题中,我将 Folder
类型与其他 Folder
s:
extension Folder {
var subFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return childrenSiblings()
}
var superFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return parentSiblings()
}
}
Pierce Darragh,您的自我回答非常好,使用 children
和 parent
标签完全符合个人偏好。另一种选择是简单地使 属性 名称与您对事物的思考方式保持一致(主要点仍然是关键位置的反转)。
例如,<User, User, FollowsPivot>
社交媒体类型关系可以表示为:
extension User {
var following: Siblings<User, User, FollowsPivot> {
return siblings(FollowsPivot.leftIDKey, FollowsPivot.rightIDKey)
}
var followers: Siblings<User, User, FollowsPivot> {
return siblings(FollowsPivot.rightIDKey, FollowsPivot.leftIDKey)
}
}
没有任何额外的扩展。我相信 siblings()
有 4 个变体,可以直接在 return
.