I'm experimenting with a server-side-Swift project using Vapor and Fluent. The idea for this project is to track athletes and their training plans and workouts. Trying to be protocol-oriented, I have a protocol named "Workout," and then various classes that conform to "Workout" such as "run," "swim," etc.
Workout.swift:
import Vapor
import FluentPostgreSQL
protocol Workout {
var title: String { get set }
var duration: Int { get set }
}
And then, for example, Run.swift:
import Vapor
import FluentPostgreSQL
final class Run: Workout, Codable {
//Conform to Workout
var title: String
var duration: Int
//New Properties
var distance: Double
var id: Int?
init(title: String, duration: Int, distance: Double) {
self.title = title
self.duration = duration
self.distance = distance
}
}
extension Run: PostgreSQLModel {}
extension Run: Content {}
When I create the model for "Training Plan," I would like to have the parameter:
var workouts = [Workout]?
to allow for any type which conforms to Workout.
TrainingPlan.swift:
import Vapor
import FluentPostgreSQL
final class TrainingPlan: Codable {
var id: Int?
var title: String
var workouts: [Workout]?
init(title: String) {
self.title = title
}
}
extension TrainingPlan: PostgreSQLModel {}
extension TrainingPlan: Content {}
I get the following errors on TrainingPlan.swift:
Type 'TrainingPlan' does not conform to protocol 'Decodable'
Type 'TrainingPlan' does not conform to protocol 'Encodable'
Changing Workout.swift to:
protocol Workout: Codable {
var title: String { get set }
var duration: Int { get set }
}
does not resolve the errors.
What would be the correct way to handle this with Fluent while still staying protocol-oriented in my data modeling? Thank you!
UPDATE (6/20/18):
Setting a generic type in TrainingPlan.swift (for types that conform to Workout) resolves the errors about conforming to Encodable / Decodable:
import Vapor
import FluentPostgreSQL
final class TrainingPlan<W: Workout>: Codable {
var id: Int?
var title: String
var workouts: [W]?
init(title: String) {
self.title = title
}
}
extension TrainingPlan: PostgreSQLModel {}
extension TrainingPlan: Content {}
extension TrainingPlan: Parameter {}
extension TrainingPlan: Migration {}
However, this implementation causes another error with adding TrainingPlan to the database migration in configure.swift:
migrations.add(model: TrainingPlan.self, database: .psql)
Produces the error:
Generic parameter 'W' could not be inferred
You need to do
swift migrations.add(model: TrainingPlan<ConcreteWorkoutType>.self, database: .psql)
So the compiler knows what the generic type is when compiling your code
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.