I am trying to fetch a series of objects from my Node.js-based, MongoDB instance using Restangular; however, I am not able to guarantee the number of objects I wish to grab by ID will always be the same.
To demonstrate, here is a code snippet of the principle:
Restangular
.several('users',
userList[0], userList[1], userList[2], userList[3], userList[4],
userList[5], userList[6], userList[7], userList[8], userList[9])
.get().then(function (users) { //...
userList is an array of IDs passed in as a part of a method:
requestUsersById = function (userList) { //...
The problem is that I cannot guarantee the size of the array. Is there a way to pass an array of IDs using Restangular? Or, am I just stuck making separate requests for each?
The ideal result would be something like:
Restangular
.several('users', userList)
.get().then(function (users) { //...
The Restangular API doesn't seem to natively support this, but I believe you can accomplish what you're trying to do by making using the apply() method.
In this case, you'd append the name of the collection users to the head of your userList array. Try this out:
// Store the userList in a new array to preserve the initial list
// (not sure if you use it somewhere else
var usersQuery = userList;
// Shift the collection name to be the first parameter in the array
usersQuery.unshift("users");
// Perform the Restangular call
Restangular
.several.apply(null,usersQuery)
.get().then(function (users) { //...
Related
Context
I have a front end app that requires an array of blog posts from the API, and when you call http://strapi-url/posts/ with a GET request, it returns all the results as objects in an array. Happy days.
Problem
Eventually I want to have more complex GET options with query params, so I need to modify the post controller and write a custom function for find().
When I modify the find() function in api/post/controllers/post.js , and just make it return the result of strapi.query('post').find(), it returns an object with keys rather than an array.
Code
async find(ctx) {
let entity = await.strapi.query('post').find();
return sanitizeEntity(entity, { model: strapi.models.post });
},
I know I could simply convert it into an array in the front end, but feels like a messy solution, and I would rather understand why it doesn't return an array, and what would be the best way to approach a solution.
The code in sanitizeEntity actually does this. You can check it out in the source code(node_modules/strapi-utils/lib/sanitize-entity.js). Also you can see this by dropping the sanitizeEntity row - you will get an array from await.strapi.query('post').find().
You can run the following test (add a custom endpoint) to see the results:
async test2(ctx) {
let entity = await strapi.query('post').find();
ctx.send({
message: 'okay',
posts: entity,
sanitizedPosts: sanitizeEntity(entity, { model: strapi.models.post })
}, 200);
}
You can solve it by making your own custom sanitize function which returns an array OR by processing the result before returning it like so:
let entity = await strapi.query('post').find();
let sanitizedEntity = sanitizeEntity(entity, { model: strapi.models.post });
//process sanitized results to an array
//return the result as array
I am very new in backbone js.
I am trying to filter some specific key and values in backbone js model extend here is the code below.
var items = ["open","close"];
var ReportModel = Backbone.Model.extend({
url: function() {
return tab+".json";
}
});
where tabe is dynamic json file name.In my json file many key value pair are there but I want to load only those key which is mentioned in items list.
I saw some where using parse function but that a;so did not work out.Please do let me know how to filter the specific keys form json using the backbone.
I also tried creating a dict from json and pass it to model like.
var ReportModel = Backbone.Model.extend({
"open":{.......}
});
but there I am getting issue.
throw new Error('A "url" property or function must be specified');
Please help me out with this.
You are missing some steps to be succesfull on your task.
First a note about the error: Backbone expects a string on the url property while you're passing a function. If you want to use a function to return your url dinamically use urlRoot.
Now onto the real coding:
since you talk about a json file that has multiple key value, maybe you should declare your model as a key-value object, and then create a Backbone.Collection that will wrap your models.
A Backbone.Collection expose a lot of utilities that can help us modeling the results, in this case by using the where() function of our collection you will be able to filter the data after you have retrieved from the remote file.
Alternatively to filter your collection if you need more control over the function you can always call the undescore function filter() .
Please refer to the official documentation of underscore and backbone, as you will find a lot of functions that can help you and most of them have an example that shows how to use them.
Now that we have everything lets create our Backbone.Collection that will wrap your already defined model:
var ReportCollection = Backbone.Collection.extend({
model: ReportModel,
urlRoot: function(){
return 'yoururl.json';
}
});
now if you want to filter the result you can simply fetch the collection and perform a filter on it:
var myReports = new ReportCollection();
//call the fetch method to retrieve the information from remote
myReports.fetch({success: function(){
//the collection has been fetched correctly, call the native where function with the key to be used as a filter.
var filteredElements = myReports.where({my_filter_key : my_filter_value});
});
in your filteredElements you will have an array of object made up of all the model that matched the key/value passed to the where function.
If you need a new Collection from that you just need to pass the result as argument: var filteredCollection = new ReportCollection(filteredElements);
You can use _.pick() in the parse method as shown below:
var items = ["open", "close"];
var ReportModel = Backbone.Model.extend({
url: function() {
return tab + ".json";
},
parse: function(response) {
return _.pick(response, items);
}
});
I'm using openerp and i need to call a python method from a web module using javascript.
this is the method:
def get_data(self, cr, uid, ids, context=None):
_logger.info('ids es %r',ids);
if context is None:
context = {}
data = {}
data['ids'] = context.get('active_ids', [])
data['model'] = context.get('active_model', 'ir.ui.menu')
data['form'] = self.read(cr, uid, ids, ['user_id', 'date_start', 'date_end'], context=context)[0]
_logger.info('data es %r',data);
_logger.info('data[form] es %r',data['form']);
return data;
however i don't know how to call this method from javascript because i don't really know what the ids parameter should be, anyways this is how i call it (i get an error because i'm not sending the ids parameter)
data = reportModel.call('get_data',[],undefined,{});
so my question is, what is the ids parameter, how does it work and what should i send to this function from javascript in order to succeed?
I am not sure you will be able to call this from javascript at all as you will need to pass in a database cursor from the connection pool for the appropriate database and you may need to use the XMLRPC interface.
That said, these methods exist on an ORM model (or transient model) and the ids parameter is the standard OpenERP pattern of passing in the IDS of records in the model this method is on that you want to process. So if this method is on the account invoice model, the IDS would be a list of ids in the account_invoice table that you want to process.
Note that you just have to have the argument, you don't have to have anything in it or use it. For example, most form on_change methods ignore it as those methods have to cater for users keying new records that don't exist in the database.
I am using angularFire v 0.5.0
On my returned object I do a $add.
What would be the best way to get the generated key?
It must be something in the succes callback of the $add, because the key will come back asynchrounlusly?
scope.settings = $firebase(ref);
scope.settings.value = {
vat: {
inclusive: true
}
}
}
scope.settings.$add (scope.settings.value).then( function ( {
scope.settings.key = ???
});
note: this is not the actual code, this is just to clarify the problem.
The actiual code is inside a factory in the loaded event, and there is a check if there is already a settings object inside the database.
This somewhat strange construct is to make it easyer for consumers of the factory to change the settings. The settings is a singleton. AngularFire does not return a array of objects, but every item is a object in the settings, with its own key.
$add returns a Firebase ref. Call name() on that ref.
scope.settings.$add(…).name();
See https://github.com/firebase/angularFire/blob/master/angularfire.js#L127.
from the angularfire docs:
The $add method takes a single argument of any type. It will append this value as a member of a list (ordered in chronological order). This is the equivalent of calling push(value) on a Firebase reference.
from the firebase docs (about push()):
Returns
A Firebase reference for the generated location.
so, i think the "key" that you want is the return value of the $add.
Maybe they've changed it in newer versions, now it works like this:
$add() will return a promise. You have to use the callback which runs on success. For example:
var something = $scope.somethings.$add({name: "foo"});
something.then(function(e) {
console.log(e.name())
});
This allows you to perform different actions based on the outcome of the save/write attempt to Firebase.
I have a simple model called BaseModel that extends from a Backbone.Model. According to Backbone.js documentation I've overridden parse method to work with a preexisting API.
The parse method is called in two different situation. When from a collection I want to fetch to grab all data. When from a model I want to fetch a specific data.
Within BaseModel to differentiate the behavior I'm doing the following.
parse : function(response, options) {
var result;
if(options.collection) {
// I'm coming from the fetch that belongs to the collection
// manipulate result here...
} else {
// I'm coming from the fetch that belongs to the model
// manipulate result here...
}
return result;
}
Is this appraoch valid or is there a better way to achieve this?
Edit 1
I thought on Andrew answer but the situation I need to manage is weird. In fact, when the parse method is called the first time (from the collection) data are parsed and properties for the model are created. Then, when the parse method is called from the model itself, additional data are parsed and properties for the model are merged to the first ones.
Edit 2
In my situation, for example, response coming from collection contains an array of objects where each object has a property a. Conversion can be applied, e.g. date obj. Then, response coming from model contains b. Also here conversion can be applied. At the end both properties will be merged into the same model but they are coming from different fetch calls.
Notice that response in collection is already an array. So, I do not to differentiate or split nothing here. I would just know that if I come from collection, I will find a, b otherwise.
Read the fetch in the collection as give me all models, while the other call as based on a model returned from the collection, enrich it by details.
Backbone.Collection also has a parse method. In my opinion the correct way is to implement it for both your BaseModel and your Collection.
The collections parse method only needs convert the data to be an array of unparsed models. It then delegates to the BaseModel parse method automatically to parse each one individually.
e.g.,
BaseModel {
parse : function(response, options) {
var result;
// I'm coming from the fetch that belongs to the model
// manipulate result here...
return result;
}
}
BaseCollection {
parse : function(response, options){
// I'm coming from the fetch that belongs to the collection
// Turn it into an array.
return response.split('mydelim');
}
}
From your edit 2, It looks like your approach is the right idea. I would however say that if I where to do it, I would test the returned object for properties rather than the context of the call so I don't need to care about the datasource,
parse : function(response, options) {
var result = {};
if(response.a){
result.c = response.a;
} else if(response.b){
result.c = response.b;
}
...
return result;
}