-
Notifications
You must be signed in to change notification settings - Fork 8
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
Error load fields #30
Comments
Is your situation similar to this issue or this issue with optional parent? |
This is |
Can you share more about the AddressModel and the schema as well? I'll look into it and figure out why this is could be happening. I am not sure immediately why this could be happening, since the way GraphQL request is executed with this library and |
This happens with any model, not just the AddressModel. Here's what the AddressModel looks like: final class AddressModel: Model {
static let schema = "addresses"
@ID(key: .id)
var id: UUID?
@Field(key: .address)
var address: String
@Field(key: .zipCode)
var zipCode: String
@Field(key: .city)
var city: String
@OptionalField(key: .longitude)
var longitude: Double?
@OptionalField(key: .latitude)
var latitude: Double?
@Parent(key: .countryID)
var country: CountryModel
@Timestamp(key: .createdAt, on: .create)
var createdAt: Date?
@Timestamp(key: .updatedAt, on: .update)
var updatedAt: Date?
@Timestamp(key: .deletedAt, on: .delete)
var deletedAt: Date?
init() {}
init(
address: String,
zipCode: String,
city: String,
longitude: Double?,
latitude: Double?,
countryID: CountryModel.IDValue
) {
self.address = address
self.zipCode = zipCode
self.city = city
self.longitude = longitude
self.latitude = latitude
self.$country.id = countryID
}
init(_ arguments: CreateAddressArguments) {
self.id = UUID()
self.address = arguments.address
self.zipCode = arguments.zipCode
self.city = arguments.city
self.longitude = arguments.longitude
self.latitude = arguments.latitude
self.$country.id = arguments.countryID
}
} In the schema, the type looks like this: Type(AddressModel.self) {
Field("id", at: \.id)
Field("address", at: \.address)
Field("zipCode", at: \.zipCode)
Field("city", at: \.city)
Field("longitude", at: \.longitude)
Field("latitude", at: \.latitude)
Field("country", at: AddressModel.getCountry, as: TypeReference<CountryModel>.self)
Field("createdAt", at: \.createdAt)
Field("updatedAt", at: \.updatedAt)
} |
I couldn't reproduce the issue. I tried getting the Here is the code I used Model classesfinal class User: Model, Content {
static var schema: String = "users"
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
init() { }
init(id: UUID? = nil, name: String) {
self.id = id
self.name = name
}
}
final class Item: Model, Content {
static let schema = "items"
@ID(key: .id)
var id: UUID?
@Field(key: "name")
var name: String
@Parent(key: "user_id")
var user: User
init() { }
init(id: UUID? = nil, name: String, userID: UUID) {
self.id = id
self.name = name
self.$user.id = userID
}
} struct Resolver {
func items(ctx: Context, _: NoArguments) async throws -> [Item] {
let res = try await Item.query(on: ctx.req.db).all()
res.forEach { item in
print("\(item.$user.id)")
}
return res
}
}
extension Item {
func owner(ctx: Context, _: NoArguments) async throws -> User? {
// I receive no fatal error here
print("\(self.$user.id)")
// No fatal error here either
return try await User.query(on: ctx.req.db).filter(\.$id == $user.id).first()
}
}
// Schema
Type(Item.self) {
Field("name", at: \.name)
Field("owner", at: Item.owner, as: TypeReference<User>.self)
}
Query {
Field("items", at: Resolver.items)
} Can share how do you fetch the |
Resolver func getAddress(
context: Context,
arguments: IDArgument
) async throws -> AddressModel {
guard
let model = try await AddressModel.query(on: context.request.db)
.filter(\.$id == arguments.id)
.first()
else {
throw Abort(.notFound, reason: "Address with id \(arguments.id) not found")
}
return model
} Schema Query {
Field("getAddress", at: GraphQLResolver.getAddress) {
Argument("id", at: \.id)
}
} |
I'll try to look into it more to find what went wrong here. Honestly, I am not sure why is this happening. My test code also uses PostgreSQL but mine worked. There is nothing out of the ordinary with the code you shared, so it should work fine. The only notable thing is that your model is I'll also share my migrations code used to build the tables for my test code, just in case you manage to find the problem from it struct CreateUser: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("users")
.id()
.field("name", .string)
.create()
}
func revert(on database: Database) async throws {
try await database.schema("users").delete()
}
}
struct CreateItem: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("items")
.id()
.field("name", .string)
.field("user_id", .uuid, .references("users", "id"))
.create()
}
func revert(on database: Database) async throws {
try await database.schema("items").delete()
}
} |
I found what the problem is, I wrote a parser for the fields that come in the request to get from the database only those fields that were requested, and there was no country field in it. This parser is more like a crutch. Perhaps you know if there is a way to get the list of requested fields in Graphiti? |
It's good to know that you figured out why the issue is happening. I don't think you can get it from From that you can access the You will have to go low level into the GraphQLSwift/GraphQL library. You'll ended up doing something like this. let gql = try ctx.req.content.decode(GraphQLRequest.self)
let fieldsRequested = try parse(source: Source(body: gql.query))
.definitions
.flatMap { def -> [Selection] in
guard let op = def as? OperationDefinition else {
return []
}
return op.selectionSet.selections
}
.compactMap { selection -> Field? in
guard let field = selection as? Field else {
return nil
}
return field
} |
Thanks for the help! |
When I try to get the parent id, I get an error "Fatal error: Cannot access field before it is initialized or fetched: country_id".
I found that all fields are empty except id
The text was updated successfully, but these errors were encountered: