How to send the child relation to the server?
hortigado opened this issue · comments
Hello, this is more than an error, it is a query. How could the child relationship be sent to the server? This works locally, but only the main model is sent to the server and I think it is correct because I am establishing that only the id is put on pizza_ids
, but there would be a way to make it automatic. This speeds up the sending of data a lot.
For better understanding I give an example. In the image you can see how I create a Customer
item and a Pizza
item as a child at the same time. I want the two data to be uploaded to the server but each one to its respective table in the parent item (Customer) only the id of the child item (pizza) is saved and vice versa in the child item the id of the parent is saved.
Could you help me with an example of how to do it if possible. Thanks
#115
my query is similar to this ticket
@hortigado that related ticket is exactly right. If you want to send a full payload (not just the id
), simply remove the @OfflineFirst
annotation.
The full association is saved to the association's table in SQLite on upsert
. When the association is sent to REST while using @OfflineFirst
, only the key value of your where
argument is sent.
@tshedor Thanks I tried removing the @OfflineFirst
and leaving only the @Rest
; but when doing them it is saved correctly locally but nothing is sent to the server, not even the Customer item.
@hortigado did you regenerate the adapter? Does your CustomerRequestTransformer
have an upsert
field?
@tshedor Yes, I am using a remote server (Appwrite) not the local of the example, I don't know if this could also cause a problem
class CustomerRequestTransformer extends RestRequestTransformer {
// A production code base would not forward to another operation
// but for testing this is convenient
@override
RestRequest get delete => get;
@override
RestRequest get get {
if (query?.where != null) {
final byId = Where.firstByField('id', query?.where);
print(byId.toString());
// member endpoint
if (byId?.value != null) {
return RestRequest(
url:
"/databases/6436b61c1e67e1fe6d5d/collections/649531713e0d37be7da4/documents/${byId!.value}",
topLevelKey: "documents");
}
}
return RestRequest(
url:
'/databases/6436b61c1e67e1fe6d5d/collections/649531713e0d37be7da4/documents',
topLevelKey: "documents");
}
// A production code base would not forward to another operation
// but for testing this is convenient
@override
RestRequest get upsert {
final id = query?.providerArgs['id'];
final method = query?.action == QueryAction.update ? "PATCH" : "POST";
final url = method == "PATCH"
? '/databases/6436b61c1e67e1fe6d5d/collections/649531713e0d37be7da4/documents/$id'
: '/databases/6436b61c1e67e1fe6d5d/collections/649531713e0d37be7da4/documents';
return RestRequest(
supplementalTopLevelData: <String, String>{
"documentId": id!.toString(),
},
method: method,
url: url,
topLevelKey: "data",
);
}
RestRequest get update {
final id = query?.providerArgs['id'];
return RestRequest(
supplementalTopLevelData: <String, String>{
"documentId": id!.toString(),
},
method: "PATCH",
url:
'/databases/6436b61c1e67e1fe6d5d/collections/649531713e0d37be7da4/documents',
topLevelKey: "data",
/* headers: <String, String>{
"documentId": id,
} */
);
}
const CustomerRequestTransformer(Query? query, RestModel? instance)
: super(query, instance);
}
Future<Customer> _$CustomerFromRest(Map<String, dynamic> data,
{required RestProvider provider,
OfflineFirstWithRestRepository? repository}) async {
return Customer(
id: data['\$id'] as String?,
firstName: data['first_name'] as String?,
lastName: data['last_name'] as String?,
pizzas: await Future.wait<Pizza>(data['pizzas']
?.map((d) => PizzaAdapter()
.fromRest(d, provider: provider, repository: repository))
.toList()
.cast<Future<Pizza>>() ??
[]));
}
Future<Map<String, dynamic>> _$CustomerToRest(Customer instance,
{required RestProvider provider,
OfflineFirstWithRestRepository? repository}) async {
return {
'first_name': instance.firstName,
'last_name': instance.lastName,
'pizzas': instance.pizzas!.first.id
};
}
@hortigado I've created a mini example to help illustrate what you'll need to do. When running the server, you'll see upsert
request body logged.
Based on what you have in the latest adapter code, your adapter wasn't regenerated for toRest
. It looks like there's an override somewhere:
'pizzas': instance.pizzas!.first.id
Can you supply your model code?
@tshedor Thanks for the example, I had already tried as it is in the example and it didn't work for me. Now I tried again and it works 100%.
Thank you if I have another question I open a new issue