Skip to content

Commit

Permalink
🛠️ refactoring: change routing from static methods to instance methods
Browse files Browse the repository at this point in the history
  • Loading branch information
edmw committed Nov 12, 2019
1 parent ba6b7d5 commit d7279c3
Show file tree
Hide file tree
Showing 63 changed files with 12,849 additions and 18,793 deletions.
19 changes: 16 additions & 3 deletions Sources/App/Adapter/Repository/MySQLFavoriteRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import Vapor
import Fluent
import FluentMySQL

/// Adapter for port `FavoriteRepository` using MySQL database.
final class MySQLFavoriteRepository: FavoriteRepository, MySQLModelRepository {
// swiftlint:disable first_where

let db: MySQLDatabase.ConnectionPool

/// Initializes the repository for **Favorites** on the specified MySQL connection pool.
/// - Parameter db: MySQL connection pool
init(_ db: MySQLDatabase.ConnectionPool) {
self.db = db
}
Expand Down Expand Up @@ -62,11 +65,13 @@ final class MySQLFavoriteRepository: FavoriteRepository, MySQLModelRepository {
}
}

/// Adds the specified list to the list of favorite lists for the specified user.
func addFavorite(_ list: List, for user: User) throws -> EventLoopFuture<Favorite> {
guard let listID = list.id else {
throw EntityError<List>.requiredIDMissing
}
guard let userID = user.id else {
throw EntityError<User>.requiredIDMissing
}
return db.withConnection { connection in
// check if the list is already a favorite
return user.favorites.isAttached(list, on: connection)
Expand All @@ -79,8 +84,16 @@ final class MySQLFavoriteRepository: FavoriteRepository, MySQLModelRepository {
.unwrap(or: EntityError<List>.lookupFailed(for: listID))
}
else {
// attach list and return created favorite
return user.favorites.attach(list, on: connection)
// favorite create
let limit = Favorite.maximumNumberOfFavoritesPerUser
return Favorite.query(on: connection)
.filter(\.userID == userID)
.count()
.max(limit, or: EntityError<Reservation>.limitReached(maximum: limit))
.transform(to:
// attach list and return created favorite
user.favorites.attach(list, on: connection)
)
}
}
}
Expand Down
15 changes: 8 additions & 7 deletions Sources/App/Adapter/Repository/MySQLInvitationRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import Vapor
import Fluent
import FluentMySQL

/// Adapter for port `InvitationRepository` using MySQL database.
final class MySQLInvitationRepository: InvitationRepository, MySQLModelRepository {
// swiftlint:disable first_where

let db: MySQLDatabase.ConnectionPool

/// Initializes the repository for **Invitations** on the specified MySQL connection pool.
/// - Parameter db: MySQL connection pool
init(_ db: MySQLDatabase.ConnectionPool) {
self.db = db
}
Expand Down Expand Up @@ -57,16 +60,14 @@ final class MySQLInvitationRepository: InvitationRepository, MySQLModelRepositor
return db.withConnection { connection in
if invitation.id == nil {
// invitation create
let limit = Invitation.maximumNumberOfInvitationsPerUser
return Invitation.query(on: connection)
.filter(\.userID == invitation.userID)
.count()
.flatMap { count in
let maximum = Invitation.maximumNumberOfInvitationsPerUser
guard count < maximum else {
throw EntityError<Invitation>.limitReached(maximum: maximum)
}
return invitation.save(on: connection)
}
.max(limit, or: EntityError<Invitation>.limitReached(maximum: limit))
.transform(to:
invitation.save(on: connection)
)
}
else {
// invitation update
Expand Down
15 changes: 8 additions & 7 deletions Sources/App/Adapter/Repository/MySQLItemRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import Fluent
import FluentSQL
import FluentMySQL

/// Adapter for port `ItemRepository` using MySQL database.
final class MySQLItemRepository: ItemRepository, MySQLModelRepository {

// swiftlint:disable first_where

let db: MySQLDatabase.ConnectionPool

/// Initializes the repository for **Items** on the specified MySQL connection pool.
/// - Parameter db: MySQL connection pool
init(_ db: MySQLDatabase.ConnectionPool) {
self.db = db
}
Expand Down Expand Up @@ -143,16 +146,14 @@ final class MySQLItemRepository: ItemRepository, MySQLModelRepository {
return db.withConnection { connection in
if item.id == nil {
// item create
let limit = Item.maximumNumberOfItemsPerList
return Item.query(on: connection)
.filter(\.listID == item.listID)
.count()
.flatMap { count in
let maximum = Item.maximumNumberOfItemsPerList
guard count < maximum else {
throw EntityError<Item>.limitReached(maximum: maximum)
}
return item.save(on: connection)
}
.max(limit, or: EntityError<Item>.limitReached(maximum: limit))
.transform(to:
item.save(on: connection)
)
}
else {
// item update
Expand Down
15 changes: 8 additions & 7 deletions Sources/App/Adapter/Repository/MySQLListRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import Vapor
import Fluent
import FluentMySQL

/// Adapter for port `ListRepository` using MySQL database.
final class MySQLListRepository: ListRepository, MySQLModelRepository {
// swiftlint:disable first_where

let db: MySQLDatabase.ConnectionPool

/// Initializes the repository for **Lists** on the specified MySQL connection pool.
/// - Parameter db: MySQL connection pool
init(_ db: MySQLDatabase.ConnectionPool) {
self.db = db
}
Expand Down Expand Up @@ -86,16 +89,14 @@ final class MySQLListRepository: ListRepository, MySQLModelRepository {
return db.withConnection { connection in
if list.id == nil {
// list create
let limit = List.maximumNumberOfListsPerUser
return List.query(on: connection)
.filter(\.userID == list.userID)
.count()
.flatMap { count in
let maximum = List.maximumNumberOfListsPerUser
guard count < maximum else {
throw EntityError<List>.limitReached(maximum: maximum)
}
return list.save(on: connection)
}
.max(limit, or: EntityError<List>.limitReached(maximum: limit))
.transform(to:
list.save(on: connection)
)
}
else {
// list update
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import Vapor
import Fluent
import FluentMySQL

/// Adapter for port `ReservationRepository` using MySQL database.
final class MySQLReservationRepository: ReservationRepository, MySQLModelRepository {
// swiftlint:disable first_where

let db: MySQLDatabase.ConnectionPool

/// Initializes the repository for **Reservations** on the specified MySQL connection pool.
/// - Parameter db: MySQL connection pool
init(_ db: MySQLDatabase.ConnectionPool) {
self.db = db
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/App/Adapter/Repository/MySQLUserRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import Vapor
import Fluent
import FluentMySQL

/// Adapter for port `UserRepository` using MySQL database.
final class MySQLUserRepository: UserRepository, MySQLModelRepository {
// swiftlint:disable first_where

let db: MySQLDatabase.ConnectionPool

/// Initializes the repository for **Users** on the specified MySQL connection pool.
/// - Parameter db: MySQL connection pool
init(_ db: MySQLDatabase.ConnectionPool) {
self.db = db
}
Expand Down
17 changes: 17 additions & 0 deletions Sources/App/Domain/Model/FavoriteRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,29 @@ import Foundation

protocol FavoriteRepository: EntityRepository {

/// Searches a favorite by the specified favorite id. The favorite must belong to the
/// specified user.
/// - Parameter id: favorite id to search for
/// - Parameter user: owner of the favorite
func find(by id: Favorite.ID, for user: User) throws -> EventLoopFuture<Favorite?>
/// Searches a favorite for the specified list. The favorite must belong to the
/// specified user.
/// - Parameter list: list for the search favorite
/// - Parameter user: owner of the favorite
func find(favorite list: List, for user: User) throws -> EventLoopFuture<Favorite?>

/// Returns all favorite lists for the specified user.
/// - Parameter user: owner of the favorites
func favorites(for user: User) throws -> EventLoopFuture<[List]>
/// Returns all favorites lists for the specified user ordered by the specified
/// sort order.
/// - Parameter user: owner of the favorites
/// - Parameter sort: lists sort order
func favorites(for user: User, sort: ListsSorting) throws -> EventLoopFuture<[List]>

/// Adds the specified list to the favorite lists for the specified user.
/// - Parameter list: list to add to the favorites
/// - Parameter user: owner of the favorites
func addFavorite(_ list: List, for user: User) throws -> EventLoopFuture<Favorite>

}
25 changes: 25 additions & 0 deletions Sources/App/Scenes/Favorites/Controller+Favorite.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Vapor

// MARK: FavoriteParameterAcceptor

protocol FavoriteParameterAcceptor {

var favoriteRepository: FavoriteRepository { get }

func requireFavorite(on request: Request, for user: User) throws -> EventLoopFuture<Favorite>

}

extension FavoriteParameterAcceptor where Self: Controller {

/// Returns the favorite specified by the favorite id given in the request’s route.
/// Asumes that the favorite id is the next routing parameter!
/// The favorite must be owned by the specified user.
func requireFavorite(on request: Request, for user: User) throws -> EventLoopFuture<Favorite> {
let favoriteID = try request.parameters.next(ID.self)
return try self.favoriteRepository
.find(by: favoriteID.uuid, for: user)
.unwrap(or: Abort(.notFound))
}

}
12 changes: 10 additions & 2 deletions Sources/App/Scenes/Favorites/FavoriteContextsBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import Vapor

class FavoriteContextsBuilder {

let favoriteRepository: FavoriteRepository
let itemRepository: ItemRepository

init(_ favoriteRepository: FavoriteRepository, _ itemRepository: ItemRepository) {
self.favoriteRepository = favoriteRepository
self.itemRepository = itemRepository
}

var user: User?

var sorting = ListsSorting.ascending(by: \List.title)
Expand Down Expand Up @@ -39,15 +47,15 @@ class FavoriteContextsBuilder {
// Then, we flatten the array of context futures to a future of an array of contexts.
// Now, we map the future of an array of contexts to the actual array of contexts.
// (better would be: use a join on the database)
return try request.make(FavoriteRepository.self)
return try self.favoriteRepository
.favorites(for: user, sort: sorting)
.flatMap { lists in
return lists.map { list in
var context = FavoriteContext(for: list)
return list.user.get(on: request).flatMap { owner in
context.list.ownerName = owner.displayName
if self.includeItemsCount {
return try request.make(ItemRepository.self)
return try self.itemRepository
.count(on: list)
.map { itemsCount in
context.list.itemsCount = itemsCount
Expand Down
Loading

0 comments on commit d7279c3

Please sign in to comment.