Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinitely recursive relations #4

Merged
merged 9 commits into from
Oct 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 143 additions & 10 deletions Sources/CrudRouter/CrudChildrenController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,163 @@ public struct CrudChildrenController<ChildT: Model & Content, ParentT: Model & C
public typealias ChildType = ChildT

public var children: KeyPath<ParentT, Children<ParentT, ChildT>>
let basePath: [PathComponentsRepresentable]
let path: [PathComponentsRepresentable]
let router: Router
let activeMethods: Set<ChildrenRouterMethod>

init(
childrenRelation: KeyPath<ParentT,
Children<ParentT, ChildT>>,
basePath: [PathComponentsRepresentable],
childrenRelation: KeyPath<ParentT, Children<ParentT, ChildT>>,
path: [PathComponentsRepresentable],
router: Router,
activeMethods: Set<ChildrenRouterMethod>
) {
let adjustedPath = path.adjustedPath(for: ChildType.self)

self.children = childrenRelation
self.basePath = basePath
self.path = adjustedPath
self.path = path
self.router = router
self.activeMethods = activeMethods
}
}

extension CrudChildrenController {
public func crud<ParentType>(
at path: PathComponentsRepresentable...,
parent relation: KeyPath<ChildType, Parent<ChildType, ParentType>>,
_ either: OnlyExceptEither<ParentRouterMethod> = .only([.read, .update]),
relationConfiguration: ((CrudParentController<ChildType, ParentType>) throws -> Void)?=nil
) throws where
ParentType: Model & Content,
ChildType.Database == ParentType.Database,
ParentType.ID: Parameter {
let baseIdPath = self.path.appending(ChildType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ParentType.self)

let fullPath = baseIdPath.appending(adjustedPath)


let allMethods: Set<ParentRouterMethod> = Set([.read, .update])
let controller: CrudParentController<ChildType, ParentType>

switch either {
case .only(let methods):
controller = CrudParentController(relation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudParentController(relation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}
}


// MARK: ChildController methods
extension CrudChildrenController {
public func crud<ChildChildType>(
at path: PathComponentsRepresentable...,
children relation: KeyPath<ChildType, Children<ChildType, ChildChildType>>,
_ either: OnlyExceptEither<ChildrenRouterMethod> = .only([.read, .readAll, .create, .update, .delete]),
relationConfiguration: ((CrudChildrenController<ChildChildType, ChildType>) throws -> Void)?=nil
) throws where
ChildChildType: Model & Content,
ChildType.Database == ChildChildType.Database,
ChildChildType.ID: Parameter {
let baseIdPath = self.path.appending(ChildType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ChildType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ChildrenRouterMethod> = Set([.read, .update])
let controller: CrudChildrenController<ChildChildType, ChildType>

switch either {
case .only(let methods):
controller = CrudChildrenController<ChildChildType, ChildType>(childrenRelation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudChildrenController<ChildChildType, ChildType>(childrenRelation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}
}

// MARK: SiblingController methods
public extension CrudChildrenController {
public func crud<ChildChildType, ThroughType>(
at path: PathComponentsRepresentable...,
siblings relation: KeyPath<ChildType, Siblings<ChildType, ChildChildType, ThroughType>>,
_ either: OnlyExceptEither<ModifiableSiblingRouterMethod> = .only([.read, .readAll, .create, .update, .delete]),
relationConfiguration: ((CrudSiblingsController<ChildChildType, ChildType, ThroughType>) throws -> Void)?=nil
) throws where
ChildChildType: Content,
ChildType.Database == ThroughType.Database,
ChildChildType.ID: Parameter,
ThroughType: ModifiablePivot,
ThroughType.Database: JoinSupporting,
ThroughType.Database == ChildChildType.Database,
ThroughType.Left == ChildType,
ThroughType.Right == ChildChildType {
let baseIdPath = self.path.appending(ChildType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ChildChildType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ModifiableSiblingRouterMethod> = Set([.read, .readAll, .create, .update, .delete])
let controller: CrudSiblingsController<ChildChildType, ChildType, ThroughType>

switch either {
case .only(let methods):
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}

public func crud<ChildChildType, ThroughType>(
at path: PathComponentsRepresentable...,
siblings relation: KeyPath<ChildType, Siblings<ChildType, ChildChildType, ThroughType>>,
_ either: OnlyExceptEither<ModifiableSiblingRouterMethod> = .only([.read, .readAll, .create, .update, .delete]),
relationConfiguration: ((CrudSiblingsController<ChildChildType, ChildType, ThroughType>) throws -> Void)?=nil
) throws where
ChildChildType: Content,
ChildType.Database == ThroughType.Database,
ChildChildType.ID: Parameter,
ThroughType: ModifiablePivot,
ThroughType.Database: JoinSupporting,
ThroughType.Database == ChildChildType.Database,
ThroughType.Right == ChildType,
ThroughType.Left == ChildChildType {
let baseIdPath = self.path.appending(ChildType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ChildChildType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ModifiableSiblingRouterMethod> = Set([.read, .readAll, .create, .update, .delete])
let controller: CrudSiblingsController<ChildChildType, ChildType, ThroughType>

switch either {
case .only(let methods):
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}
}

extension CrudChildrenController: RouteCollection {
public func boot(router: Router) throws {
let parentPath = self.basePath.appending(self.path)
let parentIdPath = self.basePath.appending(self.path).appending(ParentType.ID.parameter)
let parentPath = self.path
let parentIdPath = self.path.appending(ParentType.ID.parameter)

self.activeMethods.forEach {
$0.register(
Expand Down
36 changes: 28 additions & 8 deletions Sources/CrudRouter/CrudController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,23 @@ extension CrudController {
ModelType.Database == ParentType.Database,
ParentType.ID: Parameter {
let baseIdPath = self.path.appending(ModelType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ParentType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ParentRouterMethod> = Set([.read, .update])
let controller: CrudParentController<ModelType, ParentType>

switch either {
case .only(let methods):
controller = CrudParentController(relation: relation, basePath: baseIdPath, path: path, activeMethods: Set(methods))
controller = CrudParentController(relation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudParentController(relation: relation, basePath: baseIdPath, path: path, activeMethods: allMethods.subtracting(Set(methods)))
controller = CrudParentController(relation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}
}

Expand All @@ -56,18 +61,23 @@ extension CrudController {
ModelType.Database == ChildType.Database,
ChildType.ID: Parameter {
let baseIdPath = self.path.appending(ModelType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ChildType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ChildrenRouterMethod> = Set([.read, .update])
let controller: CrudChildrenController<ChildType, ModelType>

switch either {
case .only(let methods):
controller = CrudChildrenController(childrenRelation: relation, basePath: baseIdPath, path: path, activeMethods: Set(methods))
controller = CrudChildrenController(childrenRelation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudChildrenController(childrenRelation: relation, basePath: baseIdPath, path: path, activeMethods: allMethods.subtracting(Set(methods)))
controller = CrudChildrenController(childrenRelation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}
}

Expand All @@ -88,18 +98,23 @@ public extension CrudController {
ThroughType.Left == ModelType,
ThroughType.Right == ChildType {
let baseIdPath = self.path.appending(ModelType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ChildType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ModifiableSiblingRouterMethod> = Set([.read, .readAll, .create, .update, .delete])
let controller: CrudSiblingsController<ChildType, ModelType, ThroughType>

switch either {
case .only(let methods):
controller = CrudSiblingsController(siblingRelation: relation, basePath: baseIdPath, path: path, activeMethods: Set(methods))
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudSiblingsController(siblingRelation: relation, basePath: baseIdPath, path: path, activeMethods: allMethods.subtracting(Set(methods)))
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}

public func crud<ChildType, ThroughType>(
Expand All @@ -117,18 +132,23 @@ public extension CrudController {
ThroughType.Right == ModelType,
ThroughType.Left == ChildType {
let baseIdPath = self.path.appending(ModelType.ID.parameter)
let adjustedPath = path.adjustedPath(for: ChildType.self)

let fullPath = baseIdPath.appending(adjustedPath)

let allMethods: Set<ModifiableSiblingRouterMethod> = Set([.read, .readAll, .create, .update, .delete])
let controller: CrudSiblingsController<ChildType, ModelType, ThroughType>

switch either {
case .only(let methods):
controller = CrudSiblingsController(siblingRelation: relation, basePath: baseIdPath, path: path, activeMethods: Set(methods))
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: Set(methods))
case .except(let methods):
controller = CrudSiblingsController(siblingRelation: relation, basePath: baseIdPath, path: path, activeMethods: allMethods.subtracting(Set(methods)))
controller = CrudSiblingsController(siblingRelation: relation, path: fullPath, router: self.router, activeMethods: allMethods.subtracting(Set(methods)))
}

try controller.boot(router: self.router)

try relationConfiguration?(controller)
}
}

Expand Down
Loading