Remove all documents in a JSONStore collection (without using removeCollection() ) - ibm-mobilefirst

I am working on IBM Worklight and have question about JSONStore. How can I write a function that remove all documents in a JSONStore collection keeping the reference of the collection?
In other words I want to remove the documents without removing the collection. I can't use removeCollection() in my application because I can't quit the application and call wlCommonInit() again (that calls get and init on JSONStore).
Thanks so much for your help
Andrea

At the moment there is no API to easily achieve this. Your options are:
1.Call remove collection then init for the specific collection you want to clear and re-use. No need to call wlCommonInit again. Some pseudocode:
var collections = {
people : {...},
orders: {...},
greetings: {...}
};
var options = {...};
WL.JSONStore.get('greetings').removeCollection()
.then(function () {
return WL.JSONStore.init({greetings: collections.greetings}, options);
})
.then(function () {
//re-use the collection here
});
2.Use the find API to locate documents and the remove API to remove them. There's an example here.
You can open a feature request here.

assuming access is an accessor to your collection, you can do this :
access.findAll()
.then(function(result){
if(result.length>0)
{
access.remove(result,{push:false})
}
})
.fail(function(error_msg){
alert(error_msg);
});
but keep in mind this will not reset the ids (silly jsonstore !), so they will get shifted by the length of the collection every time you do that.
P.S.: From my experience, the removeCollection API should be avoided in case of encrypted collections because of the time it takes to init an encrypted collection on a low-performance mobile device...

Related

Mongoose Methods not stored in Session?

I'd like to use a Method defined in the Mongoose Model after saving the retrieved Object to a Session. Its not working though. Is it normal that these methods get lost after storing it to the session?
Calling Method from Mongoose Model works fine:
Puppies.findOne({_id:123}).then(puppy => puppy.bark()) // WOOF WOOF
Storing Model in Session and calling method fails:
// First Request
Puppies.findOne({_id:123}).then(puppy => {
req.session.puppy = puppy
})
// Second Request somewhere else in the app
app.use(function(req,res,next){
req.session.puppy.bark() // req.session.puppy.bark is not a function
})
I've got the exact issue, but I believe what happens is that when you're storing the variable in session, it's being toObject()'d, causing it to become a simple JavaScript object, instead of remaining as an instance of Model. I've used Model.hydrate as a means of recreating this Model instance.
app.use(function(req,res,next){
let puppyModel = mongoose.model("puppy");
let puppy = puppyModel.hydrate(req.session.puppy);
puppy.bark() // Awooo
});
This essentially is creating a new Model and then filling it with all the relevant information so it acts a clone.
Because it is needing all the relevant information to make an update (including _id if you have it), I believe you may need to extend the toObject function to return getters/virtuals:
puppySchema.set('toObject', { getters: true, virtuals: true });
Else, when it attempts to save, and it's missing the _id field, it won't be able to save it.
I do hope someone else can provide a nicer method of doing this and/or explain why when storing it it has to be converted to an object and can't remain as an instance of Model.
I think what Ciaran Blewitt said was correct. Finally worked around it by just using mongoose statics:
puppy.model.js
schema.statics.bark(puppy) {
console.log(puppy.sound)
}
Storing Model in Session and getting desired effect via static:
// First Request, storing Puppy in Session
Puppy.findOne({_id:123}).then(puppy => {
req.session.puppy = puppy
})
// Second Request somewhere else in the app
app.use(function(req,res,next){
Puppy.bark(req.session.puppy) // WOOF WOOF
})

If method returns data then load in module(view) - Aurelia

Forgive me for my ignorance but I've just started out with Aurelia/ES6 and a lot baffles me at the moment. I'm completely new to client side frameworks, so hopefully what I'm trying to achieve is possible within the framework.
So as the title indicates I'm fetching data within a class:
import {inject} from "aurelia-framework";
import {HttpClient} from "aurelia-http-client";
let baseUrl = "/FormDesigner/";
#inject(HttpClient)
export class FormData{
constructor(httpClient)
{
this.http = httpClient;
}
GetFormById(formId)
{
return this.http.get(`${baseUrl}/GetFormById/${formId}`)
.then(resp => resp.content);
};
}
Now I can see/receive the data which is great but after digging into the docs I cannot seem to figure out:
Load a separate related module/view by Id into the main view (app.html)
If no data, error and no Id passed then redirect to no-form view
Scenario:
User A navigates to "FormDesigner/#/form/3E7689F1-64F8-A5DA0099D992" at that point "A" lands on the form page, now if successful and data has been returned pass the formId into a different method elsewhere and then load in a module/view - Pages, possibly using <compose></compose>
This is probably really simple but the documentation (in my opinion) seems rather limited to someone that's new.
Really appreciate any guidance/high level concepts, as always, always much appreciated!
Regards,
Sounds like you might want to just partake in the routing lifecycle
If you are navigating to a module you can create an activate method on the view model which will be called when routing starts.
In this method you can return a promise (while you fetch data) and redirect if the fetch fails
In fact if the promise is rejected, the routing will be cancelled
If successful you can use whatever method you need to load in your module (assuming it can't just be part of the module that is being loaded since routing won't be cancelled)
Something like
activate(args, config) {
this.http.get(URL).then(resp => {
if (resp.isOk) {
// Do stuff
} else {
// Redirect
}
});
}

Node.js client for wit.ai calls multiple custom actions

I'm trying to write an example app in wit.ai. I followed the quickstart app using node.js client that is shown at https://wit.ai/docs/quickstart.
The example shown there has only one custom action. But when I try to add a new story and a new action, I see that the context is being shared between the stories. This is causing wrong behaviour(a custom action from another story is being executed).
I cannot find any example with multiple custom actions and stories. Are there any node.js or python examples other than the ones from wit.ai websites?
You need to create a context for each session, and this is a quick example (from https://github.com/wit-ai/node-wit/blob/master/examples/messenger.js):
const findOrCreateSession = (fbid) => {
let sessionId;
// Let's see if we already have a session for the user fbid
Object.keys(sessions).forEach(k => {
if (sessions[k].fbid === fbid) {
// Yep, got it!
sessionId = k;
}
});
if (!sessionId) {
// No session found for user fbid, let's create a new one
sessionId = new Date().toISOString();
sessions[sessionId] = {
fbid: fbid,
context: { // New context per session id.
_fbid_: fbid
}
}; // set context, _fid_
}
return sessionId;
};
You can find a working example at https://github.com/hunkim/Wit-Facebook.
I suppose wit engine don't store context on their side.
You 'merge' function must merge entities in different ways, depending on your app logic.
But if you story is completed, you need to clear context for next stories.
I added a built-in function clear-context and call this function from wit as action.
Check out my example.
It's not an official api, but you can understand how wit http api works.

Laravel: how to avoid json on internal api call

Laravel 4: In the context of consume-your-own-api, my XyzController uses my custom InternalAPiDispatcher class to create a Request object, push it onto a stack (per this consideration), then dispatch the Route:
class InternalApiDispatcher {
// ...
public function dispatch($resource, $method)
{
$this->request = \Request::create($this->apiBaseUrl . '/' . $resource, $method);
$this->addRequestToStack($this->request);
return \Route::dispatch($this->request);
}
To start with, I'm working on a basic GET for a collection, and would like the Response content to be in the format of an Eloquent model, or whatever is ready to be passed to a View (perhaps a repository thingy later on when I get more advanced). It seems inefficient to have the framework create a json response and then I decode it back into something else to display it in a view. What is a simple/efficient/elegant way to direct the Request to return the Response in the format I desire wherever I am in my code?
Also, I've looked at this post a lot, and although I'm handling query string stuff in the BaseContorller (thanks to this answer to my previous question) it all seems to be getting far too convoluted and I feel I'm getting lost in the trees.
EDIT: could the following be relevant (from laravel.com/docs/templates)?
"By specifying the layout property on the controller, the view specified will be created for you and will be the assumed response that should be returned from actions."
Feel free to mark this as OT if you like, but I'm going to suggest that you might want to reconsider your problem in a different light.
If you are "consuming your own API", which is delivered over HTTP, then you should stick to that method of consumption.
For all that it might seem weird, the upside is that you could actually replace that part of your application with some other server altogether. You could run different parts of your app on different boxes, you could rewrite the HTTP part completely, etc, etc. All the benefits of "web scale".
The route you're going down is coupling the publisher and the subscriber. Now, since they are both you, or more accurately your single app, this is not necessarily a bad thing. But if you want the benefits of being able to access your own "stuff" without resorting to HTTP (or at least "HTTP-like") requests, then I wouldn't bother with faking it. You'd be better off defining a different internal non-web Service API, and calling that.
This Service could be the basis of your "web api", and in fact the whole HTTP part could probably be a fairly thin controller layer on top of the core service.
It's not a million miles away from where you are now, but instead of taking something that is meant to output HTTP requests and mangling it, make something that can output objects, and wrap that for HTTP.
Here is how I solved the problem so that there is no json encoding or decoding on an internal request to my API. This solution also demonstrates use of route model binding on the API layer, and use of a repository by the API layer as well. This is all working nicely for me.
Routes:
Route::get('user/{id}/thing', array(
'uses' => 'path\to\Namespace\UserController#thing',
'as' => 'user.thing'));
//...
Route::group(['prefix' => 'api/v1'], function()
{
Route::model('thing', 'Namespace\Thing');
Route::model('user', 'Namespace\User');
Route::get('user/{user}/thing', [
'uses' => 'path\to\api\Namespace\UserController#thing',
'as' => 'api.user.thing']);
//...
Controllers:
UI: UserController#thing
public function thing()
{
$data = $this->dispatcher->dispatch('GET', “api/v1/user/1/thing”)
->getOriginalContent(); // dispatcher also sets config flag...
// use $data in a view;
}
API: UserController#thing
public function thing($user)
{
$rspns = $this->repo->thing($user);
if ($this->isInternalCall()) { // refs config flag
return $rspns;
}
return Response::json([
'error' => false,
'thing' => $rspns->toArray()
], 200);
Repo:
public function thing($user)
{
return $user->thing;
}
Here is how I achieved it in Laravel 5.1. It requires some fundamental changes to the controllers to work.
Instead of outputting response with return response()->make($data), do return $data.
This allows the controller methods to be called from other controllers with App::make('apicontroller')->methodname(). The return will be object/array and not a JSON.
To do processing for the external API, your existing routing stays the same. You probably need a middleware to do some massaging to the response. Here is a basic example that camel cases key names for the JSON.
<?php
namespace App\Http\Middleware;
use Closure;
class ResponseFormer
{
public function handle($request, Closure $next)
{
$response = $next($request);
if($response->headers->get('content-type') == 'application/json')
{
if (is_array($response->original)) {
$response->setContent(camelCaseKeys($response->original));
}
else if (is_object($response->original)) {
//laravel orm returns objects, it is a huge time saver to handle the case here
$response->setContent(camelCaseKeys($response->original->toArray()));
}
}
return $response;
}
}

Does a foreach loop work directly with a JSonStore data object store?

I create a JSonStore with a JSON formatted array of objects.
I have verified it is properly formatted.
I then try to use a dojo forEach loop on it but the JSonStore doesn't seem to have any data in it. I can specify the target in my web page URL and it shows the right data. But using console.log(myJsonStore) shows an object but I don't see the data in Firebug. I also don't see any GET for the service providing the data. It's like specifying the target path in a URL in the browser fires the GET but not when I try to trigger it in the postCreate where my foreach is located.
The answer from Ricardo, i believe is a little incorrect, seeing as the JsonRest.query function returns a dojo.Deferred.
You have a REST call being made asynchroniously through store read api - and once it returns values, it will promise to run whats set as the callback.
Try this for your loop iterator instead
storeObj.query( {} ).then(function ( results ) {
dojo.forEach( results, function( obj ) {
console.log( obj );
});
}
you can do this:
var storeObj = new JsonRest({
target: "/some/resource"
});
storeObj.query({}).forEach(function(obj){console.log(obj);});
that should do the trick