Exception while I make mutation in Hasura (Dart) - dart

I try make a post to Hasura. But I have an exception. What I do wrong?
Mutation:
mutation UpsertOperations($objects: [operation_insert_input!]!) {
insert_operation(objects: $objects, on_conflict: {constraint: operation_operationKey_serviceId_key}) {
returning {
id
}
}
}
Model 1:
const factory Operation.insert({
required int contragentId,
required int accountId,
required int serviceId,
required double amount,
required String operationKey,
required OperationType direction,
required int entityId,
required bool payInOneTransaction,
#JsonKey(name: 'external_invoice') ExternalInvoice? externalInvoice,
}) = OperationInsert;
Model 2 (relation to ExternalInvoice):
const factory ExternalInvoice.insert({
required final String name,
required final String number,
required final String url,
required final String mimeType,
}) = ExternalInvoiceInsert;
How I make Operation:
final operation = OperationInsert(
contragentId: _contragent.id,
amount: payout.valuePositive,
operationKey: payout.id.toString(),
accountId: _currentAccount.id,
serviceId: OfferStoreData.serviceId,
entityId: OfferStoreData.entityId,
direction: OperationType.outcome,
payInOneTransaction: true,
externalInvoice: _externalInvoice,
);

Related

how to pass generic type to superclass in dart?

I have code like this
class Human<T> { // <--- this is the superclass
final String name;
final T belongings;
Human({
required this.name,
required this.belongings,
});
}
class Athlete<T> extends Human { // <--- this is the subclass
final String sportType;
Athlete({
required String name,
required belongings,
required this.sportType,
}) : super(name: name, belongings: belongings);
}
final messi = Athlete<List<String>>( // <--- past List<String> as generic
name: "Lionel Messi",
belongings: ["Jersey", "Shoes"],
sportType: "Football",
);
final belonging = messi.belongings; // <-- the data type is dynamic, not List<String>
as you can see, I want belongings property to be generic, but after I pass List<String> as a generic type when instantiating an Athlete model, I still get dynamic data type like the image below, I expect it will be List<String> .
You need to add the <T> to Human, so it's extends Human<T>.
You also need to type the required belongings, parameter, either as
required T belongings,, or by using the new super-parameters feature and make it required super.belongings.
That is:
class Human<T> {
final String name;
final T belongings;
Human({
required this.name,
required this.belongings,
});
}
class Athlete<T> extends Human<T> { // <--- added <T>
final String sportType;
Athlete({
required super.name, // <--- used super.name
required super.belongings, // <--- used super.longings
required this.sportType,
}); // <--- no constructor call needed when it's all "super." parameters.
}
final messi = Athlete<List<String>>(
name: "Lionel Messi",
belongings: ["Jersey", "Shoes"],
sportType: "Football",
);
you have to declare belongings as a List within the human class like this:
final List<String> belongings;
Human({required this.belongings})

Dart Class with final computed default value

I have a device class in my application where one property needs to be computed and final plus some properties that can be set in the constructor or have default values. Here's the code:
class Device {
String idx;
String id;
String name;
String icon;
int order;
// have to create the idx before initializing the object because I can't
// figure out how to do that here.
Device(
{required this.idx,
required this.id,
required this.name,
this.icon = 'none',
this.order = -1});
// Creates a device from a JSON string
factory Device.fromJson(Map<String, dynamic> jsonData) {
return Device(
idx: jsonData['idx'],
id: jsonData['id'],
name: jsonData['name'],
icon: jsonData['icon'],
order: jsonData['order']);
}
// Returns the device as a String
static Map<String, dynamic> toMap(Device device) => {
'idx': device.idx,
'id': device.id,
'name': device.name,
'icon': device.icon,
'order': device.order
};
}
Basically I'm trying to set a unique index for the object so in my object list I can clearly identify a specific device. I'm using the Uuid package to generate a UUID for idx.
The only way I can make this work today is to create the idx in my other code that creates the object and pass it in. I read a lot of articles here that talk about different ways to solve this problem and I know I have to make the idx value a constant but I can't figure out how to do that and call the Uuid library.
I know it would look something like this:
Device(
{this.idx = const <<some calculation/expression>>,
required this.id,
required this.name,
this.icon = 'none',
this.order = -1});
removing the required modifier and putting a const before the value assignment. Nothing I've tried lets me call the Uuid method. Can someone help me understand how to do this?
Updating the code based on the answer from #jamesdlin:
import 'package:uuid/uuid.dart';
const uuid = Uuid();
class Device {
String idx;
String id;
String name;
String icon;
int order;
Device(
{String? idx,
required this.id,
required this.name,
this.icon = 'none',
this.order = -1})
: idx = idx ?? uuid.v1();
// Creates a device object from a JSON string
factory Device.fromJson(Map<String, dynamic> jsonData) {
return Device(
idx: jsonData['idx'],
id: jsonData['id'],
name: jsonData['name'],
icon: jsonData['icon'],
order: jsonData['order']);
}
// Returns the device object as a String
static Map<String, dynamic> toMap(Device device) => {
'idx': device.idx,
'id': device.id,
'name': device.name,
'icon': device.icon,
'order': device.order
};
}
This works, but I don't ever have a use case where I want the idx set manually, so how to I accomplish that? I could leave it like this, but I really want to better understand how to do exactly what I need.
The only way I can make this work today is to create the idx in my other code that creates the object and pass it in.
If you want the object to be able to generate its own UUID, you just can do:
const uuid = Uuid();
class Device {
String idx = uuid.v1(); // Or whatever UUID version you want.
...
or you if you want the caller to have the option to pass in a UUID string, you can use the typical technique of using null to achieve non-const default function arguments:
const uuid = Uuid();
class Device
String idx;
Device({String? idx, ...})
: idx = idx ?? uuid.v1(),
...
Note that attempting to make a const initializer for a UUID makes no sense. const means that the object is a compile-time constant, and furthermore, const objects are canonicalized, so a hypothetical const expression that generated a UUID would end up producing the same String for every Device, which would be the opposite of unique.
Update for you updated question
This works, but I don't ever have a use case where I want the idx set manually, so how to I accomplish that? I could leave it like this, but I really want to better understand how to do exactly what I need.
I don't understand what you mean since you quite obviously do have a use case for setting idx manually (your Device.fromJson factory constructor). If you instead mean that you don't have a use case for code from outside the Device class to manually set idx, then you can add a private constructor with the idx parameter and a public one without:
class Device {
String idx;
String id;
String name;
String icon;
int order;
Device({
required String id,
required String name,
String icon = 'none',
int order = -1,
}) : this._(
idx: uuid.v1(),
id: id,
name: name,
icon: icon,
order: order,
);
Device._({
required this.idx,
required this.id,
required this.name,
required this.icon,
required this.order,
});
// Creates a device object from a JSON string
factory Device.fromJson(Map<String, dynamic> jsonData) {
return Device._(
idx: jsonData['idx'],
id: jsonData['id'],
name: jsonData['name'],
icon: jsonData['icon'],
order: jsonData['order']);
}
}
or, since idx isn't final, .fromJson could assign it a value:
factory Device.fromJson(Map<String, dynamic> jsonData) {
return Device(
id: jsonData['id'],
name: jsonData['name'],
icon: jsonData['icon'],
order: jsonData['order'])
..idx = jsonData['idx'];
}

The argumet type ' ' can't be assign to the parameter tyepe List <>

I am trying to get a list of students from the function seasonalStudents and use it in another function studentListener
I want to use unHapyyStd but in this line unHappyStd = [StaticStudents(std.id, null, TotalStudents(std.id, null))]; I get an error The argument type TotalStudents can't be assigned to the parameter Type List<TotalStudents> , How do I fix it ?
class Toppers {
String id;
double passmark;
double failmark;
Toppers(this.id, this.passmark, this.failmark);
}
class TotalStudents {
final String id;
final Image markerIcon;
TotalStudents(
this.id,
this.markerIcon,
);
}
class StaticStudents {
final String id;
final String call;
final List<TotalStudents> totalStds;
StaticStudents(this.id, this.call, this.totalStds);
}
class Students {}
class NearPassedStudents {
String id;
double passmark;
double failmark;
NearPassedStudents(this.id, this.passmark, this.failmark);
}
class GeoStudents {
static List<NearPassedStudents> passedStudentsList = [];
}
void seasonalStudents() {
for (NearPassedStudents std in GeoStudents.passedStudentsList) {
print("student: ${std.id}");
print("student: ${std.passmark}");
print("student: ${std.failmark}");
unHappyStd = [StaticStudents(std.id, null, TotalStudents(std.id, std.passmark))];
}
Future<void> studentListener()async{
////some method
/// use it here
case studentX:
seasonalStudents();
}
}
Your problem is that the third argument in the StaticStudents constructor expects the type List<TotalStudents> but you are sending a TotalStudents object as argument:
StaticStudents(std.id, null, TotalStudents(std.id, null))
Instead, make it a List with the following if you just want a list with a single TotalStudents to be used:
StaticStudents(std.id, null, [TotalStudents(std.id, null)])
As your 3rd argument require list instead of just obj. inside your loop you can do like this
var list = <TotalStudents>[];
list.add(TotalStudents(std.id, null));
unHappyStd = [StaticStudents(std.id, null, list)];

How to create an empty typed list in dart

I am trying to convert this dart file here to use generics and I get the following error when trying to initialize an empty list in constructor.
Constant list literals can't include a type parameter as a type
argument, such as 'T'. Try replacing the type parameter with a
different
How can I create an empty list in this case. Below code can elaboreate my problem even more
old file
enum PostStatus { initial, success, failure }
class PostState extends Equatable {
const PostState({
this.status = PostStatus.initial,
this.posts = const <Post>[],
this.hasReachedMax = false,
});
final PostStatus status;
final List<Post> posts;
final bool hasReachedMax;
PostState copyWith({
PostStatus status,
List<Post> posts,
bool hasReachedMax,
}) {
return PostState(
status: status ?? this.status,
posts: posts ?? this.posts,
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
);
}
#override
List<Object> get props => [status, posts, hasReachedMax];
}
new file
class PagedState<T> extends Equatable {
const PagedState({
this.status = PagedStatus.initial,
this.items = const <T>[], //ERROR HERE
this.hasReachedMax = false,
});
final PagedStatus status;
final List<T> items;
final bool hasReachedMax;
PagedState copyWith({
PagedStatus status,
List<T> items,
bool hasReachedMax,
}) {
return PagedState(
status: status ?? this.status,
items: items ?? this.items,
hasReachedMax: hasReachedMax ?? this.hasReachedMax,
);
}
#override
List<Object> get props => [status, items, hasReachedMax];
}
As the error says, constant list literals can't use a type parameter, so you must use a non-const literal: <T>[].
However, since it's a default argument and default arguments must be constants, that won't work either. You either will need to:
Use a constant sentinel value as the default and replace it with the desired default later:
const PagedState({
List<T> items = null,
this.hasReachedMax = false,
}) : items = items ?? <T>[];
Use const [] without the explicit type parameter and let automatic type conversions do the work for you.

can built_value deserialize generics like this?

all my JSON data contains status(int), msg(String), and data(any Type). Because I'm come from java ,I want use generics。I'm writing a deserialize for a top generics with built_value, but failed.
I have try this
https://github.com/google/built_value.dart/blob/master/end_to_end_test/test/generics_serializer_test.dart.
But do not really understand.
There follows my code:
abstract class GenericValue<T>
implements Built<GenericValue<T>, GenericValueBuilder<T>> {
T get data;
int get status;
String get msg;
GenericValue._();
static Serializer<GenericValue> get serializer => _$genericValueSerializer;
factory GenericValue([updates(GenericValueBuilder<T> b)]) =
_$GenericValue<T>;
}
abstract class UserInfo implements Built<UserInfo, UserInfoBuilder> {
static Serializer<UserInfo> get serializer => _$userInfoSerializer;
String get id;
String get email;
UserInfo._();
factory UserInfo([updates(UserInfoBuilder b)]) = _$UserInfo;
}
GenericValue<UserInfo> parseUserInfo(String jsonStr) {
final parsed = json.jsonDecode(jsonStr);
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFac`enter code here`tory(specifiedType, () => GenericValueBuilder<UserInfo>
()))
.build();
Response<UserInfo> response = serializersWithBuilder.deserialize(parsed,
specifiedType: specifiedType);
return response;
}
but result is: Invalid argument(s): Unknown type on deserialization. Need either specifiedType or discriminator field.
how can it do it in right way, to deserialize JSON data like this.
String toJsonUserInfo() {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return json.encode(
serializersWithBuilder.serialize(this, specifiedType: specifiedType));
}
static GenericValue<UserInfo> fromJsonUserInfo(String jsonString) {
final specifiedType = const FullType(GenericValue, [FullType(UserInfo)]);
final serializersWithBuilder = (standardSerializers.toBuilder()
..addBuilderFactory(
specifiedType, () => GenericValueBuilder<UserInfo>()))
.build();
return serializersWithBuilder.deserialize(json.decode(jsonString),
specifiedType: specifiedType);
}
it works.

Resources