henrikac
(Henrik Christensen)
1
Hi 
After adding the following guard statement in my route I get what feels like a million error messages and not really sure why
guard let activity = try await PersonActivity.query(on: req.db)
.filter(\.$id == activityId)
.with(\.$person) { person in
person.with(\.$user)
}
.first()
else {
throw Abort(.notFound)
}
results in error messages like Initializer for conditional binding must have Optional type, not 'QueryBuilder<PersonActivity>', Cannot find 'person' in scope and Expected 'else' after 'guard' condition. But adding the guard after the query I get no errors
let activity = try await PersonActivity.query(on: req.db)
.filter(\.$id == activityId)
.with(\.$person) { person in
person.with(\.$user)
}
.first()
guard activity != nil else {
throw Abort(.notFound)
}
I hope someone knows why the first snippet results in a million errors but the second snippet doesn't 
0xTim
(Tim)
2
What's the context of the code? The error message would suggest that it's not picking up the .first() call. Maybe hidden characters, broken line spaces etc?
A classic :) Wrap your closure arguments in parenthesis in the guard and if clauses:
// Won't compile
if let x = a.first { ... } { ... }
// OK
if let x = a.first(where: { ... }) { ... }
2 Likes
henrikac
(Henrik Christensen)
4
The entire route looks like this (ignore the return type/value)
func perform(req: Request) async throws -> String {
guard let userId = req.userId else {
throw Abort(.unauthorized)
}
guard let id = req.parameters.get("id"),
let activityId = UUID(uuidString: id)
else {
throw Abort(.badRequest)
}
guard let activity = try await PersonActivity.query(on: req.db)
.filter(\.$id == activityId)
.with(\.$person) { person in
person.with(\.$user)
}
.first()
else {
throw Abort(.notFound)
}
return "Person Activity Perform"
}
where PersonActivity is a Model with @Parent person: Person and Person has @Parent user: User. At the top of my file I import both Fluent and Vapor.
EDIT:
Doing guard let activity = try await PersonActivity.query(on: req.db) ... adds the following warnings No 'async' operations occur within 'await' expression and No calls to throwing functions occur within 'try' expression - but these warnings are not shown when I split up the query and guard statement as in the second snippet in my original post.
0xTim
(Tim)
5
Do you have a sample project? Because it sounds very much like the compiler is not seeing the async functions
henrikac
(Henrik Christensen)
6
guard let activity = try await PersonActivity.query(on: req.db)
.filter(\.$id == activityId)
.with(\.$person)
.first()
else {
throw Abort(.notFound)
}
I tried to remove the nested eager loading part from the query and now there is no more errors or warnings 
final class PersonActivity: Model {
// ...
@Parent(key: "person_id")
var person: Person
// ...
}
final class Person: Model {
// ...
@Children(for: \.$person)
var activities: [PersonActivity]
@Parent(key: "user_id")
var user: User
// ...
}
final class User: Model {
// ...
@Children(for: \.$user)
var persons: [Person]
// ...
}
Am I shadow-banned or what? Of course removing the nested eager load fixes the problem, as explained above: Confused about Vapor (Fluent?) errors - #3 by gwendal.roue
henrikac
(Henrik Christensen)
8
The .first() that I am using is part of Fluent which has no .first(where:)
Fluent - .first()
Right, I did not use an example that exactly matches your code (I was on a mobile phone with mittens on my hands, sorry). But you still have to wrap you closure arguments inside parenthesis when you're in a if or guard clause (between the guard and the else { ... }). In other words, don't use the trailing closure syntax. That's how the language works, even if the compiler is too confused to provide clear error messages.
2 Likes
henrikac
(Henrik Christensen)
10
Changing from
.with(\.$person) { person in
person.with(\.$user)
}
to
.with(\.$person, { person in
person.with(\.$user)
})
fixed it! 
Thank you, I was not aware of this closure syntax rule 
1 Like