vapor / fluent

Vapor ORM (queries, models, and relations) for NoSQL and SQL databases
https://docs.vapor.codes/4.0/fluent/overview/
MIT License
1.32k stars 172 forks source link

@Children error #679

Closed josepfm closed 4 years ago

josepfm commented 4 years ago

I have created a parent-child relationship between the following two models, with the following migrations and when I run the Postman screenshot to create a user, I get the error.

Model User:

Captura de pantalla 2020-04-23 a las 18 40 12

Model Height:

Captura de pantalla 2020-04-23 a las 18 40 34

Migration User:

Captura de pantalla 2020-04-23 a las 18 41 09

Migration Height:

Captura de pantalla 2020-04-23 a las 18 41 31

Request to create User:

Captura de pantalla 2020-04-23 a las 18 42 16

Error:

[ INFO ] query create users input=[[username: "johnsmith", name: "John", password: "$2b$12$xHXMWlIiVJlsVX8JpzG8UuWnpU4lXFseV.WHow1Bh.xvbd.3HbGnq", email: "xxxxx@email.com", image: nil, updated_at: 2020-04-23 16:45:22 +0000, id: D6B703B3-E631-40D9-86AB-0CA0EAF02232, created_at: 2020-04-23 16:45:22 +0000]] Fatal error: Children relation not eager loaded, use $ prefix to access: Children<User, UserWeight>(for: [user_id]): file /Users/josepfm/Library/Developer/Xcode/DerivedData/SSS-Backend-ehnubkdoiqqgavaksaeutibbozzm/SourcePackages/checkouts/fluent-kit/Sources/FluentKit/Properties/Children.swift, line 35

0xTim commented 4 years ago

Can you show the code you're using the save the user?

josepfm commented 4 years ago

Of course.

Captura de pantalla 2020-04-23 a las 18 49 24
josepfm commented 4 years ago

The problem comes in the part of returning a public user.

I tried to create the user without that code and if it works perfectly, so I don't know where the error is.

Captura de pantalla 2020-04-23 a las 19 13 39
0xTim commented 4 years ago

@jose46moreno ah that makes sense, because things like height and weight (which I'm assuming are all children or relationship) haven't been retrieved from the database. So you'll either need a special Public type that is for something that's just been created (and has no children) or perform the query after the save in the toPublic() function. Either way you'll need a toPublic() function that queries everything for when returning users normally

josepfm commented 4 years ago

@jose46moreno ah that makes sense, because things like height and weight (which I'm assuming are all children or relationship) haven't been retrieved from the database. So you'll either need a special Public type that is for something that's just been created (and has no children) or perform the query after the save in the toPublic() function. Either way you'll need a toPublic() function that queries everything for when returning users normally

I don't quite understand what you mean exactly.

Even if I don't have any height or weight (child ratio) I shouldn't just return the empty array and that's it?

If you have a proposal for a code, I'd be happy to see it.

Yesterday, while searching, I found this:

https://forums.swift.org/t/vapor-4-eager-loading/33108

tanner0101 commented 4 years ago

As the error says, unless the relation has been eager loaded, you may only access with the $ prefix. For example:

model.myRelation // fatalError, not eager loaded
model.$myRelation.query(on: db).all() // works

This is because the relation must be fetched asynchronously.

josepfm commented 4 years ago

As the error says, unless the relation has been eager loaded, you may only access with the $ prefix. For example:

model.myRelation // fatalError, not eager loaded
model.$myRelation.query(on: db).all() // works

This is because the relation must be fetched asynchronously.

But I'm not making any calls to get.

Remember that the error occurs when calling toPublic, not any query from the database, so please open the issue again, as this does not solve the problem.

Thank you.

tanner0101 commented 4 years ago

But I'm not making any calls to get.

Not sure what you mean by that. If you attempt to access an @Parent or @Children property that is not eager loaded, you will get a crash. That is expected. Those must be accessed using $ prefix as I wrote in my last comment.

So instead of user.height it must be user.$height.query(...)....

so please open the issue again, as this does not solve the problem.

I have closed this because it is neither a bug nor a feature request that needs to be tracked. We can continue to answer your questions even though it has been closed.

0xTim commented 4 years ago

@jose46moreno you're implicitly making a call to the database in your toPublic function by attempting to access the property wrappers, which is why you're getting the error. I suggest that you pass a Request or Database object into your toPublic function and then load the required properties, or don't attempt to query them and just pass an empty array through directly