Here is my code:
var query = Post.query(on: req.db)
if needFilter == true {
query = query.filter(\.$board.$id == boardId)
}
return try await query
.with(\.$profile).all()
The above code is a bit complicated. Is there a way to write it like this❓:
return try await query
.filter(\.$board.$id == boardId, enable: needFilter)
.with(\.$profile).all()
'enable:' means this filter on/off.
Or is there another way to do it? Some convenient way?
Thanks in advance.
Using queries directly in routes is not a good idea from the repetition, abstraction and testing viewpoints. Using repositories is a much better approach. In this case, it means you can pass both the filter value and the conditional value as parameters. This will give you neater use in routes. I think your original use of the filter
inside the if
is entirely readable and not complicated, just remove the redundant == true
.
struct PostRepository: DatabaseRepository {
let database: Database
func filterIf(_ needFilter: Bool, _ boardId: Board.IDValue ) async throws -> [Post] {
var query = try await Post.query(on: database)
if needFilter {
query = query.filter(\.$board.$id == boardId)
}
return try await query
.with(\.$profile).all()
}
}
extension Application.Repositories {
var posts: PostRepository {
guard let storage = storage.makePostRepository
else { fatalError("PostRepository not configured") }
return storage(app)
}
func use(_ make: @escaping (Application) -> (PostRepository)) {
storage.makePostRepository = make
}
}
The link above gives you the rest of the code to enable this and all other repositories in your application. Then you can use it in your route as:
let posts = try await request.posts.filterIf(needFilter, boardId)
This results in a more readable, testable and maintainable solution than the accepted answer.