In mongoose, there's the timestamp: true option to a schema, which auto-populates a createdAt and updatedAt for any model item added.
Is there something similar in Aqueduct?
If not, how do I manually do so?
I currently tried this, which is failing, as usual:
#Operation.post()
Future<Response> createICD(#Bind.body() ICD body) async {
body.createdAt = DateTime.now();
final query = Query<ICD>(context)..values = body;
final insertICD = await query.insert();
return Response.ok({'state': true, 'data': insertICD});
}
Error from the above approach is:
Converting object to an encodable object failed: Instance of 'ICD'
It's failing when you send the response; you need to call asMap() on insertICD. The response body object you are providing is a standard Dart map - it doesn't have any special encoding behavior, so it doesn't know how to encode a complex type like ManagedObject. Invoke asMap() on the managed object to convert it to a standard Dart map:
#Operation.post()
Future<Response> createICD(#Bind.body() ICD body) async {
body.createdAt = DateTime.now();
final query = Query<ICD>(context)..values = body;
final insertICD = await query.insert();
return Response.ok({'state': true, 'data': insertICD.asMap()});
}
Also, see http://aqueduct.io/docs/db/validations/#update-and-insert-callbacks for setting timestamps at create/update events.
Related
I have a controller that expects to get a json payload ie
public async Task<IActionResult> InitUser([FromBody] Tenant tenant)
This is fine when a valid json payload is sent, but if no payload is sent I get the error
No input formatter was found to support the content type 'null' for use with the [FromBody] attribute
And HTTP status code 415 is returned to the client.
Is it possible to catch this case and set the json payload to some default value so that the input formatter wont throw this error?
You can remove the [FromBody] attribute and get the body directly from the HTTP request. Make sure you have the [HttpPost] Attribute decoration.
In the example below you can see how to do that in a very simple way. You can also create your own CustomAttribute and middleware if you want to make it a system wide and elegant solution.
You will also need to parse the body. For that you can use JsonConverter if you like.
[HttpPost]
public async Task<IActionResult> Index()
{
Tenant tenant;
string result;
using (var reader = new StreamReader(Request.Body))
{
var body = await reader.ReadToEndAsync();
result = body;
}
//Define the naming strategy here if you need
DefaultContractResolver contractResolver = new DefaultContractResolver
{
//NamingStrategy = new SnakeCaseNamingStrategy()
NamingStrategy = new CamelCaseNamingStrategy()
};
//Optional configuration to add in DeserializeObject constructor as second param.
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = contractResolver,
};
tenant = JsonConvert.DeserializeObject<Tenant>(result);
Console.WriteLine(tenant);
return View();
}
List returnMovies = [];
Future<List> _getData() async {
final response = await http.get("https:../getTodayMovies",
headers: {HttpHeaders.AUTHORIZATION: Acess_Token.access_token});
if (response.body != null) {
returnMovies = json.decode(response.body);
.....
setState(() {});
} else {
final responseUpcoming = await http.get("/upcoming",
headers: {HttpHeaders.AUTHORIZATION: Acess_Token.access_token});
returnMovies = json.decode(responseUpcoming.body);
}
The response.body looks like:
[{"id":394470548,"host_group_name":"heyab redda","movie_image":"..png","type":"horror","code":"X123","name":"Lovely","start_time":1554364800,"end_time":1554393600,"}]
The responseUpcoming.body looks like:
{"id":394470545,"host_group_name":"foo redda","movie_image":".png","type":"horror","code":"X123","name":"Lovely","start_time":1554364800,"end_time":1554393600,"}, {"id":394470548,"host_group_name":"foo1 redda","movie_image":"..png","type":"comic","code":"X125","name":"Lovely1","start_time":1554364800,"end_time":1554393600,"}
The error I get is: String, dynamic is not a subtype of type List<dynamic>.
In the first API call that I am doing I normally get in return an array of objects, however, when this is empty, the second API call returns a list of objects that I want to push into the array called returnMovies, how can I achieve this?? Is there any way to .push these objects in the array?? So then I want to use this array to build dynamically a Listview.builder.
Also is it correct the way I am declaring it? I am quite new on Dart. Thank you
Sounds like you are looking for addAll
returnMovies.addAll(json.decode(returnUpcoming.body))
I will suggest to use
returnMovies.addAll({your object here})
When you do this json.decode(response.body) you are getting a List of Map you should use List<dynamic> movieListData and get the items like this:
movieListData = json.decode(response.body);
returnMovies = movieListData.map((dynamic movieData) {
String id = movieData['_id'];
String host_group_name = movieData['host_group_name'];
String duration = movieData['duration'];
return new Movie(id,title, duration);
}).toList();
I have this method, which compiles with no problems in Dart 2. However at run-time I get the following error
type 'List<dynamic>' is not a subtype of type 'List<ExchangeRate>'
As you see in the code I create and return new ExchangeRate objects within .map() and then after that I return a rateEntries.toList() which I expect to be of type List<ExchangeRate>, however it seems to be inferred as type List<dynamic>!!!
#override
Future<List<ExchangeRate>> getExchangeRatesAt(DateTime time, Currency baseCurrency) async {
final http.Client client = http.Client();
final String uri = "some uri ...";
return await client
.get(uri)
.then((response) {
var jsonEntries = json.decode(response.body) as Map<String, dynamic>;
var rateJsonEntries = jsonEntries["rates"].entries.toList();
var rateEntries = rateJsonEntries.map((x) {
return new ExchangeRate(x.value.toDouble());
});
return rateEntries.toList(); // WHY IS IT RETURNING A List<dynamic> here?
})
.catchError((e) => print(e))
.whenComplete(() => client.close());
}
However if I cast it specifically to ExchangeRate it would be fine.
return rateEntries.toList().cast<ExchangeRate>();
This casting at the end seems redundant to me, why should I need it?
Well, it seems that the cast is necessary to fully define the type.
But, you can avoid the cast if you add any of the following snippets:
Give the correct type to the rateJsonEntries variable
List<dynamic> rateJsonEntries = jsonEntries["rates"].entries.toList();
For whatever reason this works in my case.
Add the parameter type to the map() method
var rateEntries = rateJsonEntries.map<ExchangeRate>((x) {
return new ExchangeRate(x.value.toDouble());
});
Is there a way to implement GraphQL in flutter?
I was trying making the API call with the query and variables objects in a JSON object.
type '_InternalLinkedHashMap' is not a subtype of type 'String' in type cast
I have been using graphql_flutter package for a few weeks now and it seems to work well enough. Here is an example:
import 'package:graphql_flutter/graphql_flutter.dart' show Client, InMemoryCache;
...
Future<dynamic> post(
String body, {
Map<String, dynamic> variables,
}) async {
final Client client = Client(
endPoint: endpoint,
cache: new InMemoryCache(),
);
final Future<Map<String, dynamic>> result =
client.query(query: body, variables: variables);
return result;
}
To use just give it the graphql and any variables. i.e. a delete mutation may look like
String deleteMutation =
'''mutation deleteItem(\$itemId: ID!) {
deleteItem(input: { itemId: \$itemId}) {
itemId
}
}'''.replaceAll('\n', ' ');
await post(deleteMutation , variables: <String, dynamic>{'itemId': itemId});
This is updated and working solution of #aqwert
import 'package:graphql_flutter/graphql_flutter.dart';
...
HttpLink link = HttpLink(uri: /*your url here*/); // you can also use headers for authorization etc.
GraphQLClient client = GraphQLClient(link: link as Link, cache: InMemoryCache());
QueryOptions query = QueryOptions(
document:
r'''
mutation deleteItem($id: String!) {
deleteItem(callId: $id)
}
''',
variables: {'id' : id}
);
var result = await client.query(query);
Im using the following code to update a Cloud Firestore collection using Dart/Flutter.
final docRef = Firestore.instance.collection('gameLevels');
docRef.document().setData(map).then((doc) {
print('hop');
}).catchError((error) {
print(error);
});
I'm trying to get the documentID created when I add the document to the collection but the (doc) parameter comes back as null. I thought it was supposed to be a documentReference?
Since it's null, I obviously can't use doc.documentID.
What am I doing wrong?
You can try the following:
DocumentReference docRef = await
Firestore.instance.collection('gameLevels').add(map);
print(docRef.documentID);
Since add() method creates new document and autogenerates id, you don't have to explicitly call document() method
Or if you want to use "then" callback try the following:
final collRef = Firestore.instance.collection('gameLevels');
DocumentReferance docReference = collRef.document();
docReferance.setData(map).then((doc) {
print('hop ${docReferance.documentID}');
}).catchError((error) {
print(error);
});
#Doug Stevenson was right and calling doc() method will return you document ID. (I am using cloud_firestore 1.0.3)
To create document you just simply call doc(). For example I want to get message ID before sending it to the firestore.
final document = FirebaseFirestore.instance
.collection('rooms')
.doc(roomId)
.collection('messages')
.doc();
I can print and see document's id.
print(document.id)
To save it instead of calling add() method, we have to use set().
await document.set({
'id': document.id,
'user': 'test user',
'text': "test message",
'timestamp': FieldValue.serverTimestamp(),
});
Using value.id ,You can fetch documentId after adding to FireStore .
CollectionReference users = FirebaseFirestore.instance.collection('candidates');
Future<void> registerUser() {
// Call the user's CollectionReference to add a new user
return users.add({
'name': enteredTextName, // John Doe
'email': enteredTextEmail, // Stokes and Sons
'profile': dropdownValue ,//
'date': selectedDate.toLocal().toString() ,//// 42
})
.then((value) =>(showDialogNew(value.id)))
.catchError((error) => print("Failed to add user: $error"));
}
If the Dart APIs are anything like other platforms, the document() method should return a document reference that has an id property with the randomly generated id for the document that's about to be added to the collection.
This worked for me
//add a passed employee to firebase collection called employees
static Future<void> addEmployee(Employee employee) async {
final CollectionReference employees = FirebaseFirestore.instance.collection('employees');
var doc = employees.doc();
employee.employeeID = doc.id;
await doc.set(employee.toJson());
}