Daniil Korotin Daniil Korotin -4 years ago 52
Swift Question

Database column names in Vapor

I'm getting familiar with Vapor 2.0 server-side Swift framework, and what confuses me is the extensive use of string literals. For example, implementing the

Model
protocol you have to parse and serialize rows like this (taken from auto-generated example project):

// Initializes the Post from the database row
init(row: Row) throws {
content = try row.get("content")
}

// Serializes the Post to the database
func makeRow() throws -> Row {
var row = Row()
try row.set("content", content)
return row
}


As you can see, for every property you use its database name twice as a string literal just for this particular protocol. And there's more in other cases — say,
Database
protocol, your own methods, etc.

Using literal strings as parameters here has obvious disadvantage of static analyser not checking them (just like key-value parameters in Objective-C), making this approach highly error-prone. Is there any best practice I'm missing?

Answer Source

You can easily minimize the number of times you repeat the string by storing it as a static property on the model and referencing that instead.

final class Post: Model {
    // Keys
    static let contentKey = "content"

    // Properties
    var content: String

    // Initializes the Post from the database row
    init(row: Row) throws {
        content = try row.get(Post.contentKey)
    }

    // Serializes the Post to the database
    func makeRow() throws -> Row {
        var row = Row()
        try row.set(Post.contentKey, content)
        return row
    }

    ...
}

extension Post: Preparation {
    static func prepare(_ database: Database) throws {
        try database.create(self) { builder in
            builder.id()
            builder.string(Post.contentKey)
        }
    }

    ...
}

Unfortunately that's probably all you can meaningfully do to make things more type-safe. There's currently no way to give the compiler information about the actual structure of the database (or any other string-y thing, like JSON). It would be really amazing if we could do that, though! Maybe some day.

(I'll look into updating the API and Web templates to include this, track the issue here: https://github.com/vapor/api-template/issues/35)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download