{"action":"created","issue":{"url":"https://api.github.com/repos/vapor/fluent-mysql/issues/71","repository_url":"https://api.github.com/repos/vapor/fluent-mysql","labels_url":"https://api.github.com/repos/vapor/fluent-mysql/issues/71/labels{/name}","comments_url":"https://api.github.com/repos/vapor/fluent-mysql/issues/71/comments","events_url":"https://api.github.com/repos/vapor/fluent-mysql/issues/71/events","html_url":"https://github.com/vapor/fluent-mysql/issues/71","id":300298651,"number":71,"title":"Vapor 3.0.0 RC 1: Support Codable Models with more complex mapping","user":{"login":"4np","id":1049693,"avatar_url":"https://avatars2.githubusercontent.com/u/1049693?v=4","gravatar_id":"","url":"https://api.github.com/users/4np","html_url":"https://github.com/4np","followers_url":"https://api.github.com/users/4np/followers","following_url":"https://api.github.com/users/4np/following{/other_user}","gists_url":"https://api.github.com/users/4np/gists{/gist_id}","starred_url":"https://api.github.com/users/4np/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/4np/subscriptions","organizations_url":"https://api.github.com/users/4np/orgs","repos_url":"https://api.github.com/users/4np/repos","events_url":"https://api.github.com/users/4np/events{/privacy}","received_events_url":"https://api.github.com/users/4np/received_events","type":"User","site_admin":false},"labels":[{"id":330494396,"url":"https://api.github.com/repos/vapor/fluent-mysql/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":{"login":"tanner0101","id":1342803,"avatar_url":"https://avatars2.githubusercontent.com/u/1342803?v=4","gravatar_id":"","url":"https://api.github.com/users/tanner0101","html_url":"https://github.com/tanner0101","followers_url":"https://api.github.com/users/tanner0101/followers","following_url":"https://api.github.com/users/tanner0101/following{/other_user}","gists_url":"https://api.github.com/users/tanner0101/gists{/gist_id}","starred_url":"https://api.github.com/users/tanner0101/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tanner0101/subscriptions","organizations_url":"https://api.github.com/users/tanner0101/orgs","repos_url":"https://api.github.com/users/tanner0101/repos","events_url":"https://api.github.com/users/tanner0101/events{/privacy}","received_events_url":"https://api.github.com/users/tanner0101/received_events","type":"User","site_admin":false},"assignees":[{"login":"tanner0101","id":1342803,"avatar_url":"https://avatars2.githubusercontent.com/u/1342803?v=4","gravatar_id":"","url":"https://api.github.com/users/tanner0101","html_url":"https://github.com/tanner0101","followers_url":"https://api.github.com/users/tanner0101/followers","following_url":"https://api.github.com/users/tanner0101/following{/other_user}","gists_url":"https://api.github.com/users/tanner0101/gists{/gist_id}","starred_url":"https://api.github.com/users/tanner0101/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tanner0101/subscriptions","organizations_url":"https://api.github.com/users/tanner0101/orgs","repos_url":"https://api.github.com/users/tanner0101/repos","events_url":"https://api.github.com/users/tanner0101/events{/privacy}","received_events_url":"https://api.github.com/users/tanner0101/received_events","type":"User","site_admin":false}],"milestone":null,"comments":1,"created_at":"2018-02-26T16:11:26Z","updated_at":"2018-02-26T21:11:48Z","closed_at":null,"author_association":"NONE","body":"I am getting nested JSON, which I am decoding / encoding in the model using `init(from decoder: Decoder) ` and `encode(to encoder: Encoder)`. While this compiles properly, the underlying table that is constructed does not contain all of the model's properties (e.g. the ones that are populated by those `init` and `encode` methods; also see [this post](https://medium.com/@sarunw/codable-in-swift-4-0-1a12e38599d8#32ee) about flattening JSON):\r\n\r\n<img width=\"221\" alt=\"screen shot 2018-02-26 at 17 14 57\" src=\"https://user-images.githubusercontent.com/1049693/36681335-98c35072-1b18-11e8-9707-3b20c59b5374.png\">\r\n\r\n_Note though, that this isn't [Support for JSON](https://github.com/vapor/fluent-mysql/issues/69)!_\r\n\r\nI am on `Vapor 3.0.0 RC 1` and `Swift 4.1`:\r\n\r\n```\r\n$ cat Package.swift \r\n...\r\n        .package(url: \"https://github.com/vapor/vapor.git\", from:\"3.0.0-rc\"), //.branch(\"beta\")),\r\n        .package(url: \"https://github.com/vapor/fluent-mysql\", from:\"3.0.0-rc\") // .branch(\"beta\")),\r\n...\r\n$ swift --version\r\nApple Swift version 4.1 (swiftlang-902.0.41 clang-902.0.31)\r\nTarget: x86_64-apple-darwin17.4.0\r\n$ \r\n```\r\n\r\n**Example JSON:**\r\n```json\r\n{\r\n    \"type\": 0,\r\n    \"measurement\": {\r\n        \"t\": 4.05,\r\n        \"p\": 77.81,\r\n        \"h\": 45.23\r\n    },\r\n    \"published_at\": \"2018-02-22T11:39:15.159Z\"\r\n}\r\n```\r\n\r\n\r\n**Example Model:**\r\n```swift\r\nenum MeasurementType: Int, Codable {\r\n    case placeA = 0\r\n    case placeB\r\n    case placeC\r\n}\r\n\r\nfinal class Measurement: Codable {\r\n    /// Model.ID\r\n    var id: Int?\r\n    var coreID: Core.ID?\r\n    var type: MeasurementType\r\n    var temperature: Double\r\n    var pressure: Double\r\n    var humidity: Double\r\n    var publishedAt: Date?\r\n    \r\n    /// Timestampable.createdAt\r\n    var createdAt: Date?\r\n    /// Timestampable.updatedAt\r\n    var updatedAt: Date?\r\n    \r\n    /// Initializer\r\n    init(id: ID? = nil, coreID: Core.ID?, type: MeasurementType, temperature: Double, pressure: Double, humidity: Double, publishedAt: Date) {\r\n        self.id = id\r\n        self.coreID = coreID\r\n        self.type = type\r\n        self.temperature = temperature\r\n        self.pressure = pressure\r\n        self.humidity = humidity\r\n        self.publishedAt = publishedAt\r\n    }\r\n    \r\n    enum RootKeys: String, CodingKey {\r\n        case id\r\n        case coreID\r\n        case type\r\n        case measurement\r\n        case publishedAt = \"published_at\"\r\n    }\r\n    \r\n    enum MeasurementKeys: String, CodingKey {\r\n        case temperature = \"t\"\r\n        case pressure = \"p\"\r\n        case humidity = \"h\"\r\n    }\r\n    \r\n    init(from decoder: Decoder) throws {\r\n        let container = try decoder.container(keyedBy: RootKeys.self)\r\n        id = try? container.decode(ID.self, forKey: .id)\r\n        coreID = try? container.decode(UUID.self, forKey: .coreID)\r\n        type = try! container.decode(MeasurementType.self, forKey: .type)\r\n        publishedAt = try container.decode(Date.self, forKey: .publishedAt)\r\n        \r\n        let measurementContainer = try container.nestedContainer(keyedBy: MeasurementKeys.self, forKey: .measurement)\r\n        temperature = try measurementContainer.decode(Double.self, forKey: .temperature)\r\n        pressure = try measurementContainer.decode(Double.self, forKey: .pressure)\r\n        humidity = try measurementContainer.decode(Double.self, forKey: .humidity)\r\n    }\r\n    \r\n    func encode(to encoder: Encoder) throws {\r\n        var container = encoder.container(keyedBy: RootKeys.self)\r\n        try? container.encode(id, forKey: .id)\r\n        try? container.encode(coreID, forKey: .coreID)\r\n        try? container.encode(type, forKey: .type)\r\n        try? container.encode(publishedAt, forKey: .publishedAt)\r\n        \r\n        var measurementContainer = container.nestedContainer(keyedBy: MeasurementKeys.self, forKey: .measurement)\r\n        try measurementContainer.encode(temperature, forKey: .temperature)\r\n        try measurementContainer.encode(pressure, forKey: .pressure)\r\n        try measurementContainer.encode(humidity, forKey: .humidity)\r\n    }\r\n}\r\n\r\n/// MARK: Model\r\nextension Measurement: Model {\r\n    /// See Model.Database\r\n    typealias Database = MySQLDatabase\r\n    \r\n    /// See Model.ID\r\n    typealias ID = Int\r\n    \r\n    /// See Model.idKey\r\n    static var idKey: WritableKeyPath<Measurement, Int?> {\r\n        return \\Measurement.id\r\n    }\r\n}\r\n\r\n/// MARK: Relations\r\nextension Measurement {\r\n    /// A relation to this pressure's core\r\n    var core: Parent<Measurement, Core>? {\r\n        return parent(\\.coreID)\r\n    }\r\n}\r\n\r\n/// Stored date stamps\r\nextension Measurement: Timestampable {\r\n    static var createdAtKey: WritableKeyPath<Measurement, Date?> {\r\n        return \\.createdAt\r\n    }\r\n    \r\n    static var updatedAtKey: WritableKeyPath<Measurement, Date?> {\r\n        return \\.updatedAt\r\n    }\r\n}\r\n\r\n/// Support dynamic migrations.\r\nextension Measurement: Migration { }\r\n\r\n/// Support encoded to and decoded from HTTP messages.\r\nextension Measurement: Content { }\r\n\r\n/// Support using as a dynamic parameter in route definitions.\r\nextension Measurement: Parameter { }\r\n```\r\n\r\n@Joannis mentioned on Slack that this might be related to the MySQL schema? Right now I don't do anything schema related in `Migration`  (`create` and `delete` do not seem to be available for `MySQL` 🤔) and let Vapor create the schema.\r\n<img width=\"1105\" alt=\"screen shot 2018-02-26 at 18 14 12\" src=\"https://user-images.githubusercontent.com/1049693/36684872-f420eb56-1b21-11e8-94f6-bc94a3ef328a.png\">\r\n\r\nIf I _do_ try to add schema creation in the Model's `Migration` protocol conformance, it appears `create` and `delete` are not available:\r\n\r\n**code:**\r\n```swift\r\n/// Support dynamic migrations.\r\nextension Measurement: Migration {\r\n    /// See Migration.prepare\r\n    static func prepare(on connection: Database.Connection) -> Future<Void> {\r\n        connection.create(self) { builder in\r\n            try builder.field(for: \\.id)\r\n            try builder.field(for: \\.coreID)\r\n            try builder.field(for: \\.type)\r\n            try builder.field(for: \\.temperature)\r\n            try builder.field(for: \\.pressure)\r\n            try builder.field(for: \\.humidity)\r\n            try builder.field(for: \\.publishedAt)\r\n            try builder.field(for: \\.createdAt)\r\n            try builder.field(for: \\.updatedAt)\r\n        }\r\n    }\r\n    \r\n    /// See Migration.revert\r\n    static func revert(on connection: Database.Connection) -> Future<Void> {\r\n        return connection.delete(self)\r\n    }\r\n}\r\n```\r\n\r\n**error:**\r\n```bash\r\nCompile Swift Module 'App' (20 sources)\r\n/.../Sources/App/Models/Measurement.swift:134:9: error: value of type 'MySQLDatabase.Connection' (aka 'MySQLConnection') has no member 'create'\r\n        connection.create(self) { builder in\r\n        ^~~~~~~~~~ ~~~~~~\r\n/.../Sources/App/Models/Measurement.swift:149:16: error: value of type 'MySQLDatabase.Connection' (aka 'MySQLConnection') has no member 'delete'\r\n        return connection.delete(self)\r\n               ^~~~~~~~~~ ~~~~~~\r\n```"},"comment":{"url":"https://api.github.com/repos/vapor/fluent-mysql/issues/comments/368651945","html_url":"https://github.com/vapor/fluent-mysql/issues/71#issuecomment-368651945","issue_url":"https://api.github.com/repos/vapor/fluent-mysql/issues/71","id":368651945,"user":{"login":"tanner0101","id":1342803,"avatar_url":"https://avatars2.githubusercontent.com/u/1342803?v=4","gravatar_id":"","url":"https://api.github.com/users/tanner0101","html_url":"https://github.com/tanner0101","followers_url":"https://api.github.com/users/tanner0101/followers","following_url":"https://api.github.com/users/tanner0101/following{/other_user}","gists_url":"https://api.github.com/users/tanner0101/gists{/gist_id}","starred_url":"https://api.github.com/users/tanner0101/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tanner0101/subscriptions","organizations_url":"https://api.github.com/users/tanner0101/orgs","repos_url":"https://api.github.com/users/tanner0101/repos","events_url":"https://api.github.com/users/tanner0101/events{/privacy}","received_events_url":"https://api.github.com/users/tanner0101/received_events","type":"User","site_admin":false},"created_at":"2018-02-26T21:11:48Z","updated_at":"2018-02-26T21:11:48Z","author_association":"OWNER","body":"Keeping this issue open to track progress of the `MySQLType` protocols..."}}
{"actor":{"display_login":"tanner0101"}}