Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 5.2 Xcode 11.4 Vapor 4.0.0 how should I code the PK in my model?

My Package.swift file looks like:

.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-rc"),
.package(url: "https://github.com/vapor/fluent.git", from: "4.0.0-rc"),
.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0-rc")

My config.swift file looks like:

app.databases.use(.postgres(
    hostname: Environment.get("DATABASE_HOST") ?? "localhost",
    username: Environment.get("DATABASE_USERNAME") ?? "postgres",
    password: Environment.get("DATABASE_PASSWORD") ?? "secret",
    database: Environment.get("DATABASE_NAME") ?? "mydb2"
), as: .psql)

My model looks like:

import Fluent
import Vapor


final class Complaint: Model, Content {

    static let schema = "cw_complaint5"

    @ID(key: .id)
    var id: UUID?

    @Field(key: "issue_description")
    var issue_description: String

    // etc.
    init() { }
}

In Xcode, the project builds OK, and this GET route runs OK:

http://localhost:8080/complaint

But when I run the POST route, I get an error in the response body:

{
    "error": true,
    "reason": "Value of type 'UUID' required for key 'id'."
}

In Vapor 3, the POST route worked fine for both inserting a new row (omit the ID in the JSON request body) and updating an existing row. The table description on PostgreSQL 11.3 looks like:

mydb2=# \d+ cw_complaint5
                                              Table "public.cw_complaint5"
        Column        |          Type           | Collation | Nullable | Default | Storage  | Stats target | Description 
----------------------+-------------------------+-----------+----------+---------+----------+--------------+-------------
 id                   | integer                 |           | not null |         | plain    |              | 
 row                  | smallint                |           |          |         | plain    |              | 
 document_number      | integer                 |           | not null |         | plain    |              |
...etc...
county_id            | integer                 |           |          |         | plain    |              | 
 city_id              | integer                 |           |          |         | plain    |              | 
 operator_id          | integer                 |           |          |         | plain    |              | 
Indexes:
    "cw_complaint5_pkey" PRIMARY KEY, btree (id)
Check constraints:
    "cw_complaint5_row_check" CHECK ("row" >= 0)
Foreign-key constraints:
    "cw_complaint5_city_id_fkey" FOREIGN KEY (city_id) REFERENCES cw_city5(id)
    "cw_complaint5_county_id_fkey" FOREIGN KEY (county_id) REFERENCES cw_county5(id)
    "cw_complaint5_operator_id_fkey" FOREIGN KEY (operator_id) REFERENCES cw_operator5(id)

(END)

The request body of the failiing POST request (update existing row) looks like:

{"id":729,"issue_description":"test","document_number":99,"api_state_code":88,"api_county_code":11,"section":22,"city_id":51,"county_id":56,"operator_id":4415}
like image 519
magula Avatar asked Nov 22 '25 05:11

magula


1 Answers

Your issue here is that the Complaint model's ID type is UUID, but in your POST request body, you are passing in an Int value. Since you are migrating an existing project that already has a database defined with integer IDs, the best solution for this is to change your model's ID type.

Because Fluent 4 attempts to support all databases, by default it only supports UUID ID types. You can have a custom ID type, like this:

@ID(custom: "id", generatedBy: .database) var id: Int?

This will allow your model to work with your current database table structure and take in integer IDs in your POST request body.

Your model will look like this in the end:

final class Complaint: Model, Content {

    static let schema = "cw_complaint5"

    @ID(custom: "id", generatedBy: .database)
    var id: Int?

    @Field(key: "issue_description")
    var issue_description: String

    // etc.
    init() { }
}
like image 87
Caleb Kleveter Avatar answered Nov 23 '25 21:11

Caleb Kleveter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!