亲子关系与 Vapor 4
Parent Child Relation with Vapor 4
我想在 Vapor 4 中的 League
和 Team
之间建立父子关系。我可以很好地创建 League
,但是当我尝试创建像这样的新团队:
{
"name": "Chicago Bulls",
"league_id": "C21827C2-8FAD-4A89-B8D3-A3E62E421258"
}
我收到这个错误:
{
"error": true,
"reason": "Value of type 'League' required for key 'league'."
}
我只想用 league_id
初始化一个 Team
,它引用 Leagues
table 中的 League
。我在 Vapor 3 中使用它,但似乎无法在 Vapor 4 中正确使用它。
请参阅下面的模型和迁移。
League
型号:
final class League: Model, Content {
init() {}
static let schema = "Leagues"
@ID(key: .id) var id: UUID?
@Field(key: .name) var name: String
@Field(key: .sport) var sport: String
@Children(for: \.$league) var teams: [Team]
init(name: String, sport: String) {
self.name = name
self.sport = sport
}
}
Team
型号:
final class Team: Model, Content {
init() {}
static let schema = "Teams"
@ID(key: .id) var id: UUID?
@Field(key: .name) var name: String
@Parent(key: .leagueId) var league: League
init(id: UUID? = nil, name: String, leagueId: UUID) throws {
self.id = id
self.name = name
self.$league.id = leagueId
}
}
CreateLeague
迁移:
struct CreateLeague: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema(League.schema)
.id()
.field(.name, .string, .required)
.field(.sport, .string, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema(League.schema).delete()
}
}
CreateTeam
迁移:
struct CreateTeam: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema(Team.schema)
.id()
.field(.name, .string, .required)
.field(.leagueId, .uuid, .required, .references(League.schema, .id))
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema(Team.schema).delete()
}
}
TeamsController
:
class TeamsController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
let teamsRoute = routes.grouped("teams")
teamsRoute.post(use: createTeam)
}
func createTeam(req: Request) throws -> EventLoopFuture<Team> {
let team = try req.content.decode(Team.self)
return team.save(on: req.db).map { team }
}
}
这是因为 属性 包装器覆盖模型的 JSON 解码的方式而失败。你有两个选择。您可以发送 JSON Fluent expects:
{
"name": "Chicago Bulls",
"league": {
"id": "C21827C2-8FAD-4A89-B8D3-A3E62E421258"
}
}
或者您可以创建一个新类型,CreateTeamData
匹配您希望发送的 JSON,并从中手动创建一个 Team
。我更喜欢第二条路线:
struct CreateTeamData: Content {
let name: String
let leagueID: UUID
}
func createTeam(req: Request) throws -> EventLoopFuture<Team> {
let data = try req.content.decode(CreateTeamData.self)
let team = Team(name: data.name, leagueID: data.leagueID)
return team.save(on: req.db).map { team }
}
我想在 Vapor 4 中的 League
和 Team
之间建立父子关系。我可以很好地创建 League
,但是当我尝试创建像这样的新团队:
{
"name": "Chicago Bulls",
"league_id": "C21827C2-8FAD-4A89-B8D3-A3E62E421258"
}
我收到这个错误:
{
"error": true,
"reason": "Value of type 'League' required for key 'league'."
}
我只想用 league_id
初始化一个 Team
,它引用 Leagues
table 中的 League
。我在 Vapor 3 中使用它,但似乎无法在 Vapor 4 中正确使用它。
请参阅下面的模型和迁移。
League
型号:
final class League: Model, Content {
init() {}
static let schema = "Leagues"
@ID(key: .id) var id: UUID?
@Field(key: .name) var name: String
@Field(key: .sport) var sport: String
@Children(for: \.$league) var teams: [Team]
init(name: String, sport: String) {
self.name = name
self.sport = sport
}
}
Team
型号:
final class Team: Model, Content {
init() {}
static let schema = "Teams"
@ID(key: .id) var id: UUID?
@Field(key: .name) var name: String
@Parent(key: .leagueId) var league: League
init(id: UUID? = nil, name: String, leagueId: UUID) throws {
self.id = id
self.name = name
self.$league.id = leagueId
}
}
CreateLeague
迁移:
struct CreateLeague: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema(League.schema)
.id()
.field(.name, .string, .required)
.field(.sport, .string, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema(League.schema).delete()
}
}
CreateTeam
迁移:
struct CreateTeam: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
return database.schema(Team.schema)
.id()
.field(.name, .string, .required)
.field(.leagueId, .uuid, .required, .references(League.schema, .id))
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
return database.schema(Team.schema).delete()
}
}
TeamsController
:
class TeamsController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
let teamsRoute = routes.grouped("teams")
teamsRoute.post(use: createTeam)
}
func createTeam(req: Request) throws -> EventLoopFuture<Team> {
let team = try req.content.decode(Team.self)
return team.save(on: req.db).map { team }
}
}
这是因为 属性 包装器覆盖模型的 JSON 解码的方式而失败。你有两个选择。您可以发送 JSON Fluent expects:
{
"name": "Chicago Bulls",
"league": {
"id": "C21827C2-8FAD-4A89-B8D3-A3E62E421258"
}
}
或者您可以创建一个新类型,CreateTeamData
匹配您希望发送的 JSON,并从中手动创建一个 Team
。我更喜欢第二条路线:
struct CreateTeamData: Content {
let name: String
let leagueID: UUID
}
func createTeam(req: Request) throws -> EventLoopFuture<Team> {
let data = try req.content.decode(CreateTeamData.self)
let team = Team(name: data.name, leagueID: data.leagueID)
return team.save(on: req.db).map { team }
}