Add func `public` which converts the computed value into an EventLoopFuture

This commit is contained in:
Simon Edelmann 2021-01-09 19:55:50 +01:00
parent c9647cb694
commit 4926af8536
4 changed files with 37 additions and 16 deletions

View File

@ -81,6 +81,19 @@ extension Todo: CRUDModel {
}
```
That computed property will be converted to an `EventLoopFuture<Public>` afterwards. If you need to run asynchronous code to create your public instance (e.g. loading relationships), you can customize that conversion. Although you will have access to the database there, this should **not** be used to do any business logic.
```swift
extension Todo: CRUDModel {
// ...
// This is the default implementation
func `public`(eventLoop: EventLoop, db: Database) -> EventLoopFuture<Public> {
eventLoop.makeSucceededFuture(self.public)
}
}
```
### Customize create / replace
You can add specific logic while create / replace. This is especially helpful, if your create / replace request should take a subset of the models properties or if you need to do special stuff while creating / replacing.

View File

@ -42,7 +42,7 @@ extension CRUDChildrenControllerProtocol {
public func indexAll(req: Request) -> EventLoopFuture<[T.Public]> {
ParentT.fetch(from: parentIdComponentKey, on: req).flatMap { parent in
parent[keyPath: self.children].query(on: req.db).all().public()
parent[keyPath: self.children].query(on: req.db).all().public(db: req.db)
}
}
@ -54,7 +54,7 @@ extension CRUDChildrenControllerProtocol {
parent[keyPath: self.children].query(on: req.db)
.filter(\._$id == id).first()
.unwrap(or: Abort(.notFound))
.public()
.public(db: req.db)
}
}
@ -65,7 +65,7 @@ extension CRUDChildrenControllerProtocol {
return ParentT.fetch(from: parentIdComponentKey, on: req).flatMap { parent in
model[keyPath: self.parent].id = parent.id!
return parent[keyPath: self.children].create(model, on: req.db)
.map { model }.public()
.map { model }.public(db: req.db)
}
}
@ -85,7 +85,7 @@ extension CRUDChildrenControllerProtocol {
model.id = oldModel.id
model._$id.exists = oldModel._$id.exists
model[keyPath: self.parent].id = parent.id!
return model.update(on: req.db).map { model }.public()
return model.update(on: req.db).map { model }.public(db: req.db)
} catch {
return req.eventLoop.makeFailedFuture(error)
}
@ -134,7 +134,7 @@ extension CRUDChildrenControllerProtocol where T: Patchable {
.flatMap { model in
do {
try model.patch(with: data)
return model.update(on: req.db).map { model }.public()
return model.update(on: req.db).map { model }.public(db: req.db)
} catch {
return req.eventLoop.makeFailedFuture(error)
}

View File

@ -25,18 +25,18 @@ extension CRUDControllerProtocol {
}
public func indexAll(req: Request) -> EventLoopFuture<[T.Public]> {
T.query(on: req.db).all().public()
T.query(on: req.db).all().public(db: req.db)
}
public func index(req: Request) -> EventLoopFuture<T.Public> {
T.fetch(from: idComponentKey, on: req).public()
T.fetch(from: idComponentKey, on: req).public(db: req.db)
}
public func create(req: Request) throws -> EventLoopFuture<T.Public> {
try T.Create.validate(on: req)
let data = try req.content.decode(T.Create.self)
let model = try T.init(from: data)
return model.save(on: req.db).map { model }.public()
return model.save(on: req.db).map { model }.public(db: req.db)
}
public func replace(req: Request) throws -> EventLoopFuture<T.Public> {
@ -47,7 +47,7 @@ extension CRUDControllerProtocol {
let model = try oldModel.replace(with: data)
model.id = oldModel.id
model._$id.exists = oldModel._$id.exists
return model.update(on: req.db).map { model }.public()
return model.update(on: req.db).map { model }.public(db: req.db)
} catch {
return req.eventLoop.makeFailedFuture(error)
}
@ -81,7 +81,7 @@ extension CRUDControllerProtocol where T: Patchable {
return T.fetch(from: idComponentKey, on: req).flatMap { model in
do {
try model.patch(with: data)
return model.update(on: req.db).map { model }.public()
return model.update(on: req.db).map { model }.public(db: req.db)
} catch {
return req.eventLoop.makeFailedFuture(error)
}

View File

@ -1,8 +1,16 @@
import Vapor
import Fluent
public protocol Publicable: Content {
associatedtype Public: Content = Self
var `public`: Public { get }
func `public`(eventLoop: EventLoop, db: Database) -> EventLoopFuture<Public>
}
extension Publicable {
public func `public`(eventLoop: EventLoop, db: Database) -> EventLoopFuture<Public> {
eventLoop.makeSucceededFuture(self.public)
}
}
extension Publicable where Public == Self {
@ -12,17 +20,17 @@ extension Publicable where Public == Self {
}
extension EventLoopFuture where Value: Publicable {
public func `public`() -> EventLoopFuture<Value.Public> {
self.map {
$0.public
public func `public`(db: Database) -> EventLoopFuture<Value.Public> {
self.flatMap {
$0.public(eventLoop: self.eventLoop, db: db)
}
}
}
extension EventLoopFuture where Value: Sequence, Value.Element: Publicable {
public func `public`() -> EventLoopFuture<[Value.Element.Public]> {
self.mapEach {
$0.public
public func `public`(db: Database) -> EventLoopFuture<[Value.Element.Public]> {
self.flatMapEach(on: self.eventLoop) {
$0.public(eventLoop: self.eventLoop, db: db)
}
}
}