I have this code below and the compiler gives the error in the title on the .all() line. It seems to indicate that the type is not being inferred but how can I force it to know it's a [UserContent]?
func getContentOfOwners(req: Request) throws -> EventLoopFuture<[UserContent]> {
let owners = try req.content.decode([User].self)
let ownerIds = owners.map({ owner in
owner.id
})
return UserContent
.query(on: req.db)
.filter(\.$owner.$id ~~ ownerIds!)
.all()
}
I can't say for certain without seeing your models, but what is the inferred type of ownerIds? My guess is that it's [User.id?], and the compiler is actually having issues with the filter, as it's expecting to do the 'contains' operation on [User.id].
Thanks. I tried getting rid of the ownerIds and having a hard coded value on the filter but it did not work. The UserContent model inherits from Model and Content. If I comment out filter the error goes away. So yes it is something to do with filtering. But just not seeing what. Is there no way to indicate the type?
import Vapor
import Fluent
final class UserContent: Model, Content {
static let schema: String = "UserContent"
@ID(key: .id)
var id: UUID?
@Field(key: "Image")
var image: String
@OptionalField(key: "Desc")
var desc: String?
@Parent(key: "User_Id")
var owner: User
@Children(for: \.$parentUserContent)
var comments: [Comment]
@Field(key: "CreatedBy")
var createdBy: String
@Timestamp(key: "CreatedOn", on: .create)
var createdOn: Date?
@Field(key: "LastModifiedBy")
var lastModifiedBy: String
@Timestamp(key: "LastModifiedOn", on: .update)
var lastModifiedOn: Date?
init(){}
init(image: String, desc: String?, owner: User, comments: [Comment]?) {
self.image = image
self.desc = desc
self.$owner.id = owner.id!
self.comments = comments ?? []
}
What I usually do when I'm trying to figure something like this out is split it up into separate assignments, and then use Xcode to see what the compiler is assuming the type is. If memory serves, you can option-click on the variable name to see the inferred type. So, for example:
let query = UserContent.query(on: req.db)
let filter = query.filter(\.$owner.$id ~~ ownerIds)
let result = filter.all()
return result
And then clicking through each of them to see where it switches from something that makes sense to either something that doesn't or <<< error type >>>
Moving this question to the “Using Swift” category. The “Development > Compiler” category is intended for discussion on developing the Swift compiler.
Sweet! I'm so happy. Thank you. I switched the code like this after I saw your suggestion. So I was trying to force casting at the filter call, but it needed an explicit type at the ownerIds level.
Are you a vapor developer or on their team?
func getContentOfOwners(req: Request) throws -> EventLoopFuture<[UserContent]> {
let owners = try req.content.decode([User].self)
let ownerIds: [UUID] = owners.map({ owner in
owner.id!
})
return UserContent
.query(on: req.db)
.filter(\.$owner.$id ~~ ownerIds)
.all()
}
I've been doing a bit of tinkering with Vapor lately, and ran into a pretty similar problem just the other day, so I figured I might be able to help out.
My last suggestion would just be swapping out
let ownerIds: [UUID] = owners.map({ owner in
owner.id!
})
for
let ownerIds: [UUID] = owners.compactMap({ owner in
owner.id
})
It's just slightly safer - if one of the owners has a nilid, the map as you have it will crash, while compactMap just skips that one, so you wind up with all non-nil IDs in your array.
Awesome thank you! By way do you know kotlin. Wondering which you prefer?
I'm putting all my eggs into Swift due to recent apple arm announcements, but I prefer kotlin as a language.
Glad you were able to solve the problem! But still type of expression is ambiguous without more context is a bad diagnostic from the compiler. So if possible can you please file a bug on https://bugs.swift.org to track down this issue?
Make sure you have import Fluent in the file you're using to perform the filters. The filter custom operators live in the Fluent module, so you won't be able to see them unless you import the module.
@xwu there's a Vapor section in the Related Projects area that this is probably a better place for