我有一种数据类型,例如文件夹,并且文件夹可以任意嵌套在彼此之间—多对多关系。为此,我建立了一个枢轴表(我正在使用MySQL)将parent_folder_id
与child_folder_id
(folders
表上的外键)相关联。在Fluent中,我将其建模为FolderToSubfoldersPivot
的方式与我的其他透视表类相同。
我现在想使用Siblings将我的Folder
类型扩展为具有subfolders
属性。代码如下:
extension Folder {
var subFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return siblings()
}
}
这类似于我为其他自定义类型编写Siblings
类型的属性的方式,所有这些都有效。但是,在这种情况下,Xcode会出现以下错误:
“兄弟姐妹(相关:通过:)”的歧义用法
我认为这是由于Folder
的类型声明中Siblings
类型的两种用法。我尝试了几种解决方法(类型别名,对带有参数的siblings(related:through:)
方法的显式调用等)无济于事。
如何使siblings()
功能正常工作?还是我需要从头开始重新实现Siblings struct才能完成我想做的事情?
答案 0 :(得分:1)
摆弄了一段时间之后,我找到了答案。
可以在this highlighted segment on GitHub中找到Fluent的siblings
便利功能的实现。为了方便讨论,我在下面复制了它:
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
是枢轴的右手类型,而Related
是左手类型时,使用上述代码段中的第一个函数。同样,当情况相反时,使用第二个功能。
当我使用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
来表示您正在寻找当前类型的孩子(也属于同一类型),而parentSiblings
则是在寻找当前类型的孩子(即相同类型)。它们之间的区别在于对siblings
的内部调用,其中Through.leftIDKey
和Through.rightIDKey
在第二个函数中进行了切换。这是因为我如何构造数据透视表(即,左侧列为parent_folder_id
,右侧列为child_folder_id
)。
这些功能的用法与常规siblings
函数的用法相似。就我在问题中的情况而言,我将Folder
类型与其他Folder
的类型相关联:
extension Folder {
var subFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return childrenSiblings()
}
var superFolders: Siblings<Folder, Folder, FoldersToSubfoldersPivot> {
return parentSiblings()
}
}
答案 1 :(得分:1)
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
中使用。