Vapor 2, One to Many relation

464 views Asked by At

Do you have any example of how to create One to Many relation using Vapor 2? There are some examples of how to do this, but they use the old version of Vapor.

Thank you for all suggestions.

1

There are 1 answers

0
jonaszmclaren On BEST ANSWER

I have found a solution. Here is simple example of an owner having many cars, maybe will be helpful for someone.

Owner:

final class Owner: Model {
    static let idKey = "id"
    static let nameKey = "name"
    static let carsKey = "cars"

    var name: String
    let storage = Storage()

    var cars: Children<Owner, Car> {
        return children()
    }


    init(name: String) {
        self.name = name
    }

    init(row: Row) throws {
        name = try row.get(Owner.nameKey)
    }

    func makeRow() throws -> Row {
        var row = Row()
        try row.set(Owner.nameKey, name)
        return row
    }
}

extension Owner: Preparation {

    static func prepare(_ database: Database) throws {
        try database.create(self) { builder in
            builder.id()
            builder.string(Owner.nameKey)
        }
    }

    static func revert(_ database: Database) throws {
        try database.delete(self)
    }
}

extension Owner: JSONConvertible {

    convenience init(json: JSON) throws {
        try self.init(
            name: json.get(Owner.nameKey)
        )
    }

    func makeJSON() throws -> JSON {
        var json = JSON()
        try json.set(Owner.idKey, id)
        try json.set(Owner.nameKey, name)
        try json.set(Owner.carsKey, try cars.all())
        return json
    }
}

extension Owner: ResponseRepresentable { }

extension Owner: Updateable {
    public static var updateableKeys: [UpdateableKey<Owner>] {
        return [
            UpdateableKey(Owner.nameKey, String.self) { owner, text in
                owner.name = name
            }
        ]
    }
}

Car:

final class Car: Model {
    static let idKey = "id"
    static let makeKey = "make"
    static let modelKey = "model"
    static let ownerIdKey = "owner_id"

    var make: String
    var model: String
    var ownerId: Identifier
    let storage = Storage()

    var owner: Parent<Car, Owner> {
        return parent(id: ownerId)
    }

    init(make: String, model: String, ownerId: Identifier) {
        self.make = make
        self.model = model
        self.ownerId = ownerId
    }

    init(row: Row) throws {
        make = try row.get(Car.makeKey)
        model = try row.get(Car.modelKey)
        ownerId = try row.get(Car.ownerIdKey)
    }

    func makeRow() throws -> Row {
        var row = Row()
        try row.set(Car.makeKey, make)
        try row.set(Car.modelKey, model)
        try row.set(Car.ownerIdKey, ownerId)
        return row
    }
}

extension Car: JSONConvertible {

    convenience init(json: JSON) throws {
        try self.init(
            make: json.get(Car.makeKey),
            model: json.get(Car.modelKey),
            ownerId: json.get(Car.ownerIdKey)
        )
    }

    func makeJSON() throws -> JSON {
        var json = JSON()
        try json.set(Car.idKey, id)
        try json.set(Car.makeKey, make)
        try json.set(Car.modelKey, model)
        try json.set(Car.ownerIdKey, ownerId)
        return json
    }
}

extension Car: ResponseRepresentable {}

extension Car: Preparation {

    static func prepare(_ database: Database) throws {
        try database.create(self) { builder in
            builder.id()
            builder.string(Car.makeKey)
            builder.string(Car.modelKey)
            builder.foreignId(for: Owner.self)
        }
    }

    static func revert(_ database: Database) throws {
        try database.delete(self)
    }
}

extension Car: Updateable {
    public static var updateableKeys: [UpdateableKey<Car>] {
        return [
            UpdateableKey(Car.makeKey, String.self) { car, make in
                car.make = make
            }
        ]
    }
}