Model records ordering in Spine.js - model-view-controller

As I can see in the Spine.js sources the Model.each() function returns Model's records in the order of their IDs. This is completely unreliable in scenarios where ordering is important: long person list etc.
Can you suggest a way to keep original records ordering (in the same order as they've arrived via refresh() or similar functions) ?
P.S.
Things are even worse because by default Spine.js internally uses new GUIDs as IDs. So records order is completely random which unacceptable.
EDIT:
Seems that in last commit https://github.com/maccman/spine/commit/116b722dd8ea9912b9906db6b70da7948c16948a
they made it possible, but I have not tested it myself because I switched from Spine to Knockout.

Bumped into the same problem learning spine.js. I'm using pure JS, so i was neglecting the the contact example http://spinejs.com/docs/example_contacts which helped out on this one. As a matter of fact, you can't really keep the ordering from the server this way, but you can do your own ordering with javascript.
Notice that i'm using the Element Pattern here. (http://spinejs.com/docs/controller_patterns)
First you set the function which is gonna do the sorting inside the model:
/*Extending the Student Model*/
Student.extend({
nameSort: function(a,b) {
if ((a.name || a.email) > (b.name || b.email))
return 1;
else
return -1
}
});
Then, in the students controller you set the elements using the sort:
/*Controller that manages the students*/
var Students = Spine.Controller.sub({
/*code ommited for simplicity*/
addOne: function(student){
var item = new StudentItem({item: student});
this.append(item.render());
},
addAll: function(){
var sortedByName = Student.all().sort(Student.nameSort);
var _self = this;
$.each(sortedByName, function(){_self.addOne(this)});
},
});
And that's it.

Related

How Should Complex ReQL Queries be Composed?

Are there any best practices or ReQL features that that help with composing complex ReQL queries?
In order to illustrate this, imagine a fruits table. Each document has the following structure.
{
"id": 123,
"name": "name",
"colour": "colour",
"weight": 5
}
If we wanted to retrieve all green fruits, we might use the following query.
r
.db('db')
.table('fruits')
.filter({colour: 'green'})
However, in more complex cases, we might wish to use a variety of complex command combinations. In such cases, bespoke queries could be written for each case, but this could be difficult to maintain and could violate the Don't Repeat Yourself (DRY) principle. Instead, we might wish to write bespoke queries which could chain custom commands, thus allowing complex queries to be composed in a modular fashion. This might take the following form.
r
.db('db')
.table('fruits')
.custom(component)
The component could be a function which accepts the last entity in the command chain as its argument and returns something, as follows.
function component(chain)
{
return chain
.filter({colour: 'green'});
};
This is not so much a feature proposal as an illustration of the problem of complex queries, although such a feature does seem intuitively useful.
Personally, my own efforts in resolving this problem have involved the creation of a compose utility function. It takes an array of functions as its main argument. Each function is called, passed a part of the query chain, and is expected to return an amended version of the query chain. Once the iteration is complete, a composition of the query components is returned. This can be viewed below.
function compose(queries, parameters)
{
if (queries.length > 1)
{
let composition = queries[0](parameters);
for (let index = 1; index < queries.length; index++)
{
let query = queries[index];
composition = query(composition, parameters);
};
return composition;
}
else
{
throw 'Must be two or more queries.';
};
};
function startQuery()
{
return RethinkDB;
};
function filterQuery1(query)
{
return query.filter({name: 'Grape'});
};
function filterQuery2(query)
{
return query.filter({colour: 'Green'});
};
function filterQuery3(query)
{
return query.orderBy(RethinkDB.desc('created'));
};
let composition = compose([startQuery, filterQuery1, filterQuery2, filterQuery3]);
composition.run(connection);
It would be great to know whether something like this exists, whether there are best practises to handle such cases, or whether this is an area where ReQL could benefit from improvements.
In RethinkDB doc, they state it clearly: All ReQL queries are chainable
Queries are constructed by making function calls in the programming
language you already know. You don’t have to concatenate strings or
construct specialized JSON objects to query the database. All ReQL
queries are chainable. You begin with a table and incrementally chain
transformers to the end of the query using the . operator
You do not have to compose another thing which just implicit your code, which gets it more difficult to read and be unnecessary eventually.
The simple way is assign the rethinkdb query and filter into the variables, anytime you need to add more complex logic, add directly to these variables, then run() it when your query is completed
Supposing I have to search a list of products with different filter inputs and getting pagination. The following code is exposed in javascript (This is simple code for illustration only)
let sorterDirection = 'asc';
let sorterColumnName = 'created_date';
var buildFilter = r.row('app_id').eq(appId).and(r.row('status').eq('public'))
// if there is no condition to start up, you could use r.expr(true)
// append every filter into the buildFilter var if they are positive
if (escapedKeyword != "") {
buildFilter = buildFilter.and(r.row('name').default('').downcase().match(escapedKeyword))
}
// you may have different filter to add, do the same to append them into buildFilter.
// start to make query
let query = r.table('yourTableName').filter(buildFilter);
query.orderBy(r[sorterDirection](sorterColumnName))
.slice(pageIndex * pageSize, (pageIndex * pageSize) + pageSize).run();

HandsOnTable manualRowMove not updating the DOM

The manualRowMove works fine visually but the underlying dom is not getting updated. After manualRowMove the HOT.getData() is showing the old sequence of data and not the latest sequence after row swap.
Please advise what I am doing wrong or is it a bug.
Turning on manualRowMove and moving rows around does not affect the original data source. HOT.getData() returns the original data source, which is not what the current state of the table is.
Plugins like manualRowMove, manualColMove, columnSorting are just abstractions that sit on top of the data layer. They maintain state on the handsontable object (ie the sortIndex attribute) which basically act as lookup tables from what the authors call "logical index" to "physical index". Read more about it here: https://github.com/handsontable/handsontable/wiki/Understanding-column-sorting-plugin
It seems like you are trying to allow users to sort the order of the table then save that order. You'll have to roll your own func to walk the table and use a method like getDataAtRow() to get data in table order.
the way I fixed this was to use a PHP script to push the new order to the database on the server (there needs to be some < / > swap logic, it isn't that easy in PHP land, but it is doable), in theory you could recollect the grid and "refresh" it but I didn't feel it was necessary. Obviously the original json from my database is listed by the order
afterRowMove: function (oldIndex, newIndex){
$.post('../ajax/partsOrder.php?id=212&new_parts_order=' + newIndex + '&old_parts_order=' + oldIndex, function(data) {
var msg = '';
if (data.err!=0 || data.url==0) {
msg = 'Error: ' + data.err;
}
else {
msg = 'Success: ' + data.msg;
}
console.log('partsOrder.php says: '+msg);
},"json");
}
PS: I think this is a major omission from handontable, I was not impressed that the getData() doesn't simply represent the gui. In fact it's borderline criminal that they even worked on the gui at all without this

Meteor: filter data in publish or on client

In Meteor I want to work on the document level when having a Mongo database and according to sources, what I have to watch out for is expensive publications so today my question is:
How would I go about publishing documents with relations, would I follow the relational-type of query where we would find assignment details with an assignment id like this:
Meteor.publish('someName', function () {
var empId = "dj4nfhd56k7bhb3b732fd73fb";
var assignmentData = Assignment.find({ employee_id: empId });
return AssignmentDetails.find({ assignment_id: $in [ assignment ] });
});
or should we rather take an approach like this where we skip the filtering step in the publish and instead publish every assignment_detail and handle that filter on the client:
Meteor.publish('someName', function () {
var empId = "dj4nfhd56k7bhb3b732fd73fb";
var assignmentData = Assignment.find({ employee_id: empId });
var detailData = AssignmentDetails.find({ employee_id: empId });
return [ assignmentData, detailData];
});
I guess this is a question of whether the amount of data being searched trough on the server should be more then or if the amount of data being transferred to the client should be bigger.
Which of these would be most cost effective for the server?
It's a matter of opinion, but if possible I would strongly recommend attaching employee_id to docs in AssignmentDetails, as you have in the second example. You're correct in suggesting that publications are expensive, but much more so if the publication function is more complex than necessary, and you can reduce your pub function to one line if you have employee_id in AssignmentDetails (even where there are many employee_ids for each assignment) by just searching on that. You don't even need to return that field to the client (you can specify the fields to return in your find), so the only incurred overhead would be in database storage (which is v. cheap) and adding it to inserted/updated AssignmentDetails docs (which would be imperceptible). The actual amount of data transferred would be the same as in the first case.
The alternative of just publishing everything might be fine for a small collection, but it really depends on the number of assignments, and it's not going to be at all scalable this way. You need to send the entire collection to the client every time a client connects, which is expensive and time-consuming at both ends if it's more than a MB or so, and there isn't really any way round that overhead when you're talking about a dynamic (i.e. frequently-changing) collection, which I think you are (whereas for largely static collections you can do things with localStorage and poll-and-diff).

Sorting a NotesDocumentCollection based on a date field in SSJS

Using Server side javascript, I need to sort a NotesDcumentCollection based on a field in the collection containing a date when the documents was created or any built in field when the documents was created.
It would be nice if the function could take a sort option parameter so I could put in if I want the result back in ascending or descending order.
the reason I need this is because I use database.getModifiedDocuments() which returns an unsorted notesdocumentcollection. I need to return the documents in descending order.
The following code is a modified snippet from openNTF which returns the collection in ascending order.
function sortColByDateItem(dc:NotesDocumentCollection, iName:String) {
try{
var rl:java.util.Vector = new java.util.Vector();
var tm:java.util.TreeMap = new java.util.TreeMap();
var doc:NotesNotesDocument = dc.getFirstDocument();
while (doc != null) {
tm.put(doc.getItemValueDateTimeArray(iName)[0].toJavaDate(), doc);
doc = dc.getNextDocument(doc);
}
var tCol:java.util.Collection = tm.values();
var tIt:java.util.Iterator = tCol.iterator();
while (tIt.hasNext()) {
rl.add(tIt.next());
}
return rl;
}catch(e){
}
}
When you construct the TreeMap, pass a Comparator to the constructor. This allows you to define custom sorting instead of "natural" sorting, which by default sorts ascending. Alternatively, you can call descendingMap against the TreeMap to return a clone in reverse order.
This is a very expensive methodology if you are dealing with large number of documents. I mostly use NotesViewEntrycollection (always sorted according to the source view) or view navigator.
For large databases, you may use a view, sorted according to the modified date and navigate through entries of that view until the most recent date your code has been executed (which you have to save it somewhere).
For smaller operations, Tim's method is great!

Handling parameters from dynamic form for one-to-many relationships in grails

My main question here is dealing with the pramas map when having a one-to-many relationship managed within one dynamic form, as well as best practices for dealing with one-to-many when editing/updating a domain object through the dynamic form. The inputs for my questions are as follows.
I have managed to hack away a form that allows me to create the domain objects shown below in one Dynamic form, since there is no point in having a separate form for creating phone numbers and then assigning them to a contact, it makes sense to just create everything in one form in my application. I managed to implement something similar to what I have asked in my Previous Question (thanks for the people who helped out)
class Contact{
String firstName
String lastName
// ....
// some other properties
// ...
static hasMany = [phones:Phone]
static mapping = {
phones sort:"index", cascade: "all-delete-orphan"
}
}
class Phone{
int index
String number
String type
Contact contact
static belongsTo = [contact:Contact]
}
I basically managed to get the values from the 'params' map and parse them on my own and create the domain object and association manually. I.e. i did not use the same logic that is used in the default scaffolding, i.e.
Contact c = new Contact(params)
etc...., i just looped through all the params and hand crafted my domain objects and saved them and everything works out fine.
My controller has code blocks that look like this (this is stripped down, just to show a point)
//create the contact by handpicking params values
def cntct = new Contact()
cntct.firstName = params.firstName
cntct.lastName = params.lastName
//etc...
//get array of values for number,type
def numbers = params['phone.number']
def types = params['phone.type']
//loop through one of the arrays and create the phones
numbers.eachWithIndex(){ num, i ->
//create the phone domain object from
def phone = new Phone()
phone.number = num
phone.type = types[i]
phone.index = i
cntct.addToPhones(phone)
}
//save
My questions are as follows:
What is the best practice of handeling such a situation, would using Command objects work in this case, if yes where can i found more info about this, all the examples I have found during my search deal with one-to-one relationships, I couldn't find an example for one-to-many?
What is the best way to deal with the relatiohsips of the phones in this case, in terms of add/removing phones when editing the contact object. I mean the creation logic is simple since I have to always create new phones on save, but when dealing with updating a contact, the user might have removed a phone and/or editing an exiting one and/or added some new phones. Right now what I do is just delete all the phones a contact has and re-create them according to what was posted by the form, but I feel that's not the best way to do it, I also don't think looping over the existing ones and comparing with the posted values and doing a manual diff is the best way to do it either, is there a best practice on how to deal with this?
Thanks, hopefully the questions are clear.
[edit] Just for more information, phone information can be added and deleted dynamically using javascript (jquery) within the form [/edit]
disclaimer: i do not know if the following approach works when using grails. Let me know later.
See better way for dynamic forms. The author says:
To add LineItems I have some js that calculates the new index and adds that to the DOM. When deleting a LineItem i have to renumber all the indexes and it is what i would like to avoid
So what i do
I have a variable which stores the next index
var nextIndex = 0;
When the page is loaded, i perform a JavaScript function which calculates how many child The collection has and configure nextIndex variable. You can use JQuery or YUI, feel free.
Adding a child statically
I create a variable which store the template (Notice {index})
var child = "<div>"
+= "<div>"
+= "<label>Name</label>"
+= "<input type="text" name=\"childList[{index}].name\"/>"
+= "</div>"
+= "</div>"
When the user click on the Add child button, i replace {index} - by using regex - by the value stored in the nextIndex variable and increment by one. Then i add to the DOM
See also Add and Remove HTML elements dynamically with Javascript
Adding a child dinamically
Here you can see The Paolo Bergantino solution
By removing
But i think it is the issue grow up when deleting. No matter how many child you remove, does not touch on the nextIndex variable. See here
/**
* var nextIndex = 3;
*/
<input type="text" name="childList[0].name"/>
<input type="text" name="childList[1].name"/> // It will be removed
<input type="text" name="childList[2].name"/>
Suppose i remove childList1 What i do ??? Should i renumber all the indexes ???
On the server side i use AutoPopulatingList. Because childList1 has been removed, AutoPopulatingList handles it as null. So on the initialization i do
List<Child> childList = new AutoPopulatingList(new ElementFactory() {
public Object createElement(int index) throws ElementInstantiationException {
/**
* remove any null value added
*/
childList.removeAll(Collections.singletonList(null));
return new Child();
}
});
This way, my collection just contains two child (without any null value) and i do not need to renumber all the indexes on the client side
About adding/removing you can see this link where i show a scenario wich can gives you some insight.
See also Grails UI plugin
Thanks,
Your answer brought some insight for me to do a wider search and I actually found a great post that covers all the inputs in my question. This is just a reference for anyone reading this. I will write a blog entry on how I implemented my case soon, but this link should provide a good source of ino with a working exmaple.
http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/
Most of the time I use ajax to manage such problem.
So when the user clicks add new phone I get the template UI from the server for manageability purpose ( the UI just same GSP template that I use to edit, update the phone), so this way you are not mixing your UI with your js code, whenever you want to change the UI you have to deal only with our GSP code.
Then after getting the UI I add it to the page using jquery DOM manipulation. Then after filling the form when they hit add(save) the request is sent to the server via ajax and is persisted immediately.
When the user clicks edit phone the same UI template is loaded from the server filled with existing phone data, then clicking update will update the corresponding phone immediately via ajax, and same thing applies to delete operation.
But one day I got an additional scenario for the use case that says, "until I say save contact no phone shall be saved on the backend, also after adding phones to the contact on the ui if navigate away to another page and come back later to the contact page the phones I added before must be still there." ugh..
To do this I started using the Session, so the above operations I explained will act on the phone list object I stored on the session instead of the DB. This is simple perform all the operation on the phonesInSession but finally dont forget to do this(delete update):
phonesToBeDeleted = phonesInDB - phonesInSession
phonesToBeDeleted.each{
contact.removeFromPhones(it)
it.delete()
}
I know I dont have to put a lot of data in session but this is the only solution I got for my scenario.
If someone has got similar problem/solution please leave a comment.
First, in all your input fields names you add an #:
<input type="text" name="references[#].name"/>
Second, add call a function before submitting:
<g:form action="save" onsubmit="replaceAllWildCardsWithConsecutiveNumbers();">
Third, this is the code for the function that you call before submitting the form:
function replaceAllWildCardsWithConsecutiveNumbers(){
var inputs = $('form').find("[name*='#']");
var names = $.map(inputs, function(el) { return el.name });
var uniqueNames = unique(names);
for (index in uniqueNames) {
var uniqueName = uniqueNames[index];
replaceWildCardsWithConsecutiveNumbers("input", uniqueName);
replaceWildCardsWithConsecutiveNumbers("select", uniqueName);
}
}
function unique(array){
return array.filter(function(el, index, arr) {
return index === arr.indexOf(el);
});
}
function replaceWildCardsWithConsecutiveNumbers(inputName, name){
counter = 0;
$(inputName + "[name='" + name + "']").each(function (i, el) {
var curName = $(this).attr('name');
var newName = curName.replace("#", counter);
$(this).attr('name', newName);
counter += 1;
});
}
Basically, what the code for replaceAllWildCardsWithConsecutiveNumbers() does, is to create a list for all input (or select) elements whose name contains an #. Removes the duplicates. And then iterates over them replacing the # with a number.
This works great if you have a table and you are submitting the values to a command object's list when creating a domain class for the first time. If you are updating I guess you'll have to change the value of counter to something higher.
I hope this helps someone else since I was stuck on this issue for a while myself.

Resources