Ember 2.5 ember-cmi-mirage trying to get a subset of collection - ember-cli

Using ember 2.5 and ember-cli-mirage 0.2)
In my mirage/config.js , I am trying to get a subset ofa collection, for pagination purpose) using the slice() function
var books = schema.book.all().slice(startItem, endItem );
but I get an error:
schema.book.all(...).slice is not a function
I tried also , same error
var books = schema.book.all();
var items = books.slice(startItem, endItem );
Here is my mirage/config.js
export default function() {
....
this.get('/books', function(schema, request) {
const pageNumber = request.queryParams['page[number]'];
const pageSize = request.queryParams['page[size]'];
const startItem= (pageNumber - 1) * pageSize;
const endItem = (pageNumber * pageSize) - 1;
var books = schema.book.all().slice(startItem, endItem );
....
return books;
});
}
It seems that slice() is a function of ArrayProxy.. however this may not help as with a JSONAPISerializer
I'm a little bit lost as all exampels I can google relate to Ember 1.13 and not Ember 2.5...

This is because Collection is array-like, but not a true array. Precisely for this reason, in the next beta release we'll expose a .models property which has the underlying array.
For now, try calling .toArray() on your schema.book.all() collection, and then calling slice on it.
To take advantage of the Serializer layer, make sure to return a new Collection from your handler:
import Collection from 'ember-cli-mirage/orm/collection';
this.get('/books', (schema, request) => {
let books = schema.book.all().toArray().slice(...);
return new Collection('book', books);
});

Related

Persisting a Modified Database in Chrome APP using chrome.storage API

I am using SQL.js for SQLite in my chrome app , I am loading external db file to perform query , now i want to save my changes to local storage to make it persistent , it is already define here-
https://github.com/kripken/sql.js/wiki/Persisting-a-Modified-Database
i am using the same way as defined in the article-
function toBinString (arr) {
var uarr = new Uint8Array(arr);
var strings = [], chunksize = 0xffff;
// There is a maximum stack size. We cannot call String.fromCharCode with as many arguments as we want
for (var i=0; i*chunksize < uarr.length; i++){
strings.push(String.fromCharCode.apply(null, uarr.subarray(i*chunksize, (i+1)*chunksize)));
}
return strings.join('');
}
function toBinArray (str) {
var l = str.length,
arr = new Uint8Array(l);
for (var i=0; i<l; i++) arr[i] = str.charCodeAt(i);
return arr;
}
save data to storage -
var data =toBinString(db.export());
chrome.storage.local.set({"localDB":data});
and to get data from storage-
chrome.storage.local.get('localDB', function(res) {
var data = toBinArray(res.localDB);
//sample example usage
db = new SQL.Database(data);
var result = db.exec("SELECT * FROM user");
});
Now when i make a query , i am getting this error -
Error: file is encrypted or is not a database
is there any differnces for storing values in chrome.storage and localStorage ? because its working fine using localStorage, find the working example here-
http://kripken.github.io/sql.js/examples/persistent.html
as document sugggested here -
https://developer.chrome.com/apps/storage
we don't need to use stringify and parse in chrome.storage API unlike localStorage, we can directly saves object and array.
when i try to save result return from db.export without any conversion, i am getting this error-
Cannot serialize value to JSON
So please help me guys what will be the approach to save db export in chrome's storage, is there anything i am doing wrong?

global mongodb cursor in Meteor App

I'm trying to build an app with Meteor and I'm new to the framework.
What I want to do is have the Mongocursor that get returned in the tablets functions with the search parameter to be used in colors functions. Currently in colors I'm just getting the reactive variable again and running the Tablets.find(). But I'm going to have many other functions like this so I want to use the same Mongo cursor. Is it possible to create a global Mongo cursor from the tablets functions that will also be reactive.
The code below is my setup:
Template.tabletsList.helpers({
tablets: function() {
// read the user's last search (if any)
var query = Template.instance().query.get();
// sort options
var options = {sort: {manufacturer: 1}};
if ($.isEmptyObject(query)) {
// if the user didn't input a search just find all tablets
var tabletCursor = Tablets.find({}, options);
return tabletCursor;
}
else {
// find all tablets matching the search expression
return Tablets.find(query, options);
}
},
colors: function() {
var query = Template.instance().query.get();
if ($.isEmptyObject(query))
var allTablets = Tablets.find().fetch();
else
var allTablets = Tablets.find(query).fetch();
var color = '';
var colors = [];
allTablets.forEach(function (tablet) {
for (var i=0; i<tablet.specs.color.length; i++) {
color = tablet.specs.color[i];
if ($.inArray(color, colors) === -1) {
colors.push(color);
}
}
});
return colors.sort();
}
You can create a global helper:
Template.registerHelper('tablets',function(query){
var options = {sort: {manufacturer: 1}};
if ($.isEmptyObject(query)) query = {};
return = Tablets.find(query, options);
});
Then from anywhere in your code you can access this with:
var tabletCursor = UI._globalHelpers.tablets(query);
If you don't have access to query everwhere you can add it to Session or create a new reactive variable to hold it.

Windows Mobile Service Queries in WP8

http://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started-with-data-dotnet/#update-app
I'm the beginner of WP8, and I follow the above tutorial to create a mobile service that
I can insert/update/delete/query the tables in the cloud.
My question is, in the Query function (RefreshToDoItem):
private void RefreshTodoItems()
{
// This query filters out completed TodoItems.
items = todoTable
.Where(todoItem => todoItem.Complete == false)
.ToCollectionView();
ListItems.ItemsSource = items;
}
The "items" is a MobileServiceCollectionView object which can be used as a data source to display in a container.
But how can I retrive one of these result - I mean the data of a specific "field / column" that I can used for other purposes ??
Thanks a lot!
You can use the other methods of the query object, such as ToListAsync or ToEnumerableAsync, and get the data from there:
// This query filters out completed TodoItems.
items = await todoTable
.Where(todoItem => todoItem.Complete == false)
.ToListAsync();
var firstItem = items.First();
var text = firstItem.Text;

Extending TokenStream

I am trying to index into a document a field with one term that has a payload.
Since the only constructor of Field that can work for me takes a TokenStream, I decided to inherit from this class and give the most basic implementation for what I need:
public class MyTokenStream : TokenStream
{
TermAttribute termAtt;
PayloadAttribute payloadAtt;
bool moreTokens = true;
public MyTokenStream()
{
termAtt = (TermAttribute)GetAttribute(typeof(TermAttribute));
payloadAtt = (PayloadAttribute)GetAttribute(typeof(PayloadAttribute));
}
public override bool IncrementToken()
{
if (moreTokens)
{
termAtt.SetTermBuffer("my_val");
payloadAtt.SetPayload(new Payload(/*bye[] data*/));
moreTokens = false;
}
return false;
}
}
The code which was used while indexing:
IndexWriter writer = //init tndex writer...
Document d = new Document();
d.Add(new Field("field_name", new MyTokenStream()));
writer.AddDocument(d);
writer.Commit();
And the code that was used during the search:
IndexSearcher searcher = //init index searcher
Query query = new TermQuery(new Term("field_name", "my_val"));
TopDocs result = searcher.Search(query, null, 10);
I used the debugger to verify that call to IncrementToken() actually sets the TermBuffer.
My problem is that the returned TopDocs instance returns no documents, and I cant understand why... Actually I started from TermPositions (which gives me approach to the Payload...), but it also gave me no results.
Can someone explain to me what am I doing wrong?
I am currently using Lucene .NET 2.9.2
After you set the TermBuffer you need to return true from IncrementToken, you return false when you have nothing to feed the TermBuffer with anymore

Does Mongoose provide access to previous value of property in pre('save')?

I'd like to compare the new/incoming value of a property with the previous value of that property (what is currently saved in the db) within a pre('save') middleware.
Does Mongoose provide a facility for doing this?
The accepted answer works very nicely. An alternative syntax can also be used, with the setter inline with the Schema definition:
var Person = new mongoose.Schema({
name: {
type: String,
set: function(name) {
this._previousName = this.name;
return name;
}
});
Person.pre('save', function (next) {
var previousName = this._previousName;
if(someCondition) {
...
}
next();
});
Mongoose allows you to configure custom setters in which you do the comparison. pre('save') by itself won't give you what you need, but together:
schema.path('name').set(function (newVal) {
var originalVal = this.name;
if (someThing) {
this._customState = true;
}
});
schema.pre('save', function (next) {
if (this._customState) {
...
}
next();
})
I was looking for a solution to detect changes in any one of multiple fields. Since it looks like you can't create a setter for the full schema, I used a virtual property. I'm only updating records in a few places so this is a fairly efficient solution for that kind of situation:
Person.virtual('previousDoc').get(function() {
return this._previousDoc;
}).set(function(value) {
this._previousDoc = value;
});
Let's say your Person moves and you need to update his address:
const person = await Person.findOne({firstName: "John", lastName: "Doe"});
person.previousDoc = person.toObject(); // create a deep copy of the previous doc
person.address = "123 Stack Road";
person.city = "Overflow";
person.state = "CA";
person.save();
Then in your pre hooks, you would just need to reference properties of _previousDoc such as:
// fallback to empty object in case you don't always want to check the previous state
const previous = this._previousDoc || {};
if (this.address !== previous.address) {
// do something
}
// you could also assign custom properties to _previousDoc that are not in your schema to allow further customization
if (previous.userAddressChange) {
} else if (previous.adminAddressChange) {
}
Honestly, I tried the solutions posted here, but I had to create a function that would store the old values in an array, save the values, and then see the difference.
// Stores all of the old values of the instance into oldValues
const oldValues = {};
for (let key of Object.keys(input)) {
if (self[key] != undefined) {
oldValues[key] = self[key].toString();
}
// Saves the input values to the instance
self[key] = input[key];
}
yield self.save();
for (let key of Object.keys(newValues)) {
if (oldValues[key] != newValues[key]) {
// Do what you need to do
}
}
What I do is use this.constructor within the pre-save route to access the current value in the database.
const oldData = this.constructor.findById(this.id)
You can then grab the specific key you're looking for from the oldData to work with as you see fit :)
let name = oldData.name
Note that this works well for simple data such as strings, but I have found that it does not work well for subschema, as mongoose has built in functionality that runs first. Thus, sometimes your oldData will match your newData for a subschema. This can be resolved by giving it it's own pre-save route!