【问题标题】:Vapor 4: creating a protocol that contains a Fluent ParentProperty results in compiler errorsVapor 4:创建包含 Fluent ParentProperty 的协议会导致编译器错误
【发布时间】:2021-10-24 02:08:21
【问题描述】:

我有一大堆 Fluent (Vapor 4) 模型,它们都有这样的父字段:

final class Location: Model, Content {
  // .. bunch of other properties

  @Parent(key: FieldKeys.campaign)
  var campaign: Campaign
}

现在,我想制作一个可以应用于所有这些模型的协议,如下所示:

protocol HasCampaignId: Model {
  var _campaign: ParentProperty<Self, Campaign> { get }
  func belongsToCampaign(_ campaignID: Campaign.IDValue) throws -> Self
}

extension HasCampaignId {
  func belongsToCampaign(_ campaignID: Campaign.IDValue) throws -> Self {
    if self._campaign.id != campaignID {
      throw Abort(.forbidden)
    }

    return self
  }
}

只是一个方便的小功能,我可以将其应用于HasCampaignId 的任何模型实例,就是这样。遗憾的是,这无法编译,我收到错误 Property '_campaign' must be declared internal because it matches a requirement in internal protocol 'HasCampaignId'。我可以将协议公开,但随后又出现另一个错误:Property '_campaign' must be as accessible as its enclosing type because it matches a requirement in protocol 'HasCampaignId'

我可以像这样更改协议:

protocol HasCampaignId: Model {
  var campaign: Campaign { get }
  func belongsToCampaign(_ campaignID: Campaign.IDValue) throws -> Self
}

extension HasCampaignId {
  func belongsToCampaign(_ campaignID: Campaign.IDValue) throws -> Self {
    if self.campaign.id != campaignID {
      throw Abort(.forbidden)
    }

    return self
  }
}

但这需要我加载活动关系,这通常不是我想要的 - 否则它会因致命错误而崩溃:Fatal error: Parent relation not eager loaded, use $ prefix to access: Parent&lt;Loot, Campaign&gt;(key: campaign_id)

我的协议中的campaign 属性也不能应用属性包装器。

那么我怎样才能有一个需要ParentProperty 字段的协议呢?如何解决编译器错误?

【问题讨论】:

    标签: vapor vapor-fluent


    【解决方案1】:

    从 Swift 5.4 和 5.5 开始 - 你不能。协议中的属性包装器已经被提出,但它们没有实现并且不可能强制执行。在 Fluent 中尝试和解决这些限制方面付出了很多努力,但目前无法做到您正在尝试的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-06
      • 2020-08-17
      • 2018-11-27
      • 1970-01-01
      相关资源
      最近更新 更多