Skip to content

Commit

Permalink
merging shadowed ids
Browse files Browse the repository at this point in the history
  • Loading branch information
justinbmeyer committed Oct 30, 2012
2 parents 0a748d4 + b64b2d7 commit 4fa3f8e
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 15 deletions.
2 changes: 1 addition & 1 deletion model/elements/elements.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var unique = function( items ) {
* @return {String}
*/
identity: function() {
var id = this[this.constructor.id],
var id = this.__get(this.constructor.id),
constructor = this.constructor;
return (constructor._fullName + '_' + (constructor.escapeIdentity ? encodeURIComponent(id) : id)).replace(/ /g, '_');
},
Expand Down
18 changes: 18 additions & 0 deletions model/elements/elements_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
steal("can/model/elements", 'funcunit/qunit', function(){

module("jquery/model/elements")

test("identity uses the real id", function(){
var Person = can.Model.extend({
id:'ssn',
_fullName: 'Person'
},{
ssn: function() {
return 'xxx-xx-'+this.attr('ssn').substring(7);
}
})

equals(new Person({ssn:'987-65-4321'}).identity(),'Person_987-65-4321');
})

})
16 changes: 16 additions & 0 deletions model/elements/qunit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="../../../funcunit/qunit/qunit.css" />
<script type='text/javascript' src='../../../steal/steal.js?can/model/elements/elements_test.js'></script>
</head>
<body>

<h1 id="qunit-header">Model Elements Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<div id="test-content"></div>
<ol id="qunit-tests"></ol>
<div id="qunit-test-area"></div>
</body>
</html>
28 changes: 15 additions & 13 deletions model/list/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ steal('can/util', 'can/model/elements', function(can) {
//used for namespacing
id = 0,
getIds = function( item ) {
return item[item.constructor.id]
return item.__get(item.constructor.id);
},
ajaxMaker = can.Model._ajax,

Expand Down Expand Up @@ -338,17 +338,16 @@ steal('can/util', 'can/model/elements', function(can) {
var list = [],
constructor = this[0].constructor,
underscored = constructor._fullName,
idName = constructor.id,
test = new RegExp(underscored + "_([^ ]+)"),
matches, val, args = getArgs(arguments);

for ( var i = 0; i < args.length; i++ ) {
if ( args[i].nodeName && (matches = args[i].className.match(test)) ) {
// If this is a dom element
val = this.grep(function(item){ return item[idName] === matches[1] })[0];
val = this.grep(function(item){ return getIds(item) === matches[1] })[0];
} else {
// Else an id was provided as a number or string.
val = this.grep(function(item){ return item[idName] === args[i] })[0];
val = this.grep(function(item){ return getIds(item) === args[i] })[0];
}
val && list.push(val)
}
Expand All @@ -375,7 +374,6 @@ steal('can/util', 'can/model/elements', function(can) {
var list = [],
constructor = this[0].constructor,
underscored = constructor._fullName,
idName = constructor.id,
test = new RegExp(underscored + "_([^ ]+)"),
matches, val;
args = getArgs(arguments)
Expand All @@ -387,8 +385,8 @@ steal('can/util', 'can/model/elements', function(can) {
var inst = this[i],
found = false
for ( var a = 0; a < args.length; a++ ) {
var id = (args[a].nodeName && (matches = args[a].className.match(test)) && matches[1]) || (typeof args[a] == 'string' || typeof args[a] == 'number' ? args[a] : args[a][idName]);
if ( inst[idName] == id ) {
var id = (args[a].nodeName && (matches = args[a].className.match(test)) && matches[1]) || (typeof args[a] == 'string' || typeof args[a] == 'number' ? args[a] : getIds(args[a]));
if ( getIds(inst) == id ) {
list.push.apply(list, this.splice(i, 1));
args.splice(a, 1);
found = true;
Expand Down Expand Up @@ -520,12 +518,17 @@ steal('can/util', 'can/model/elements', function(can) {
newVal,
curVal;

var id = this.constructor.id;
function getId(obj) {
return obj.attr ? obj.attr(id) : obj[id];
}

for ( var i = 0; i < len; i++ ) {
newVal = items[i];
curVal = null;

if ( can.Observe.canMakeObserve(newVal) && newVal[this.constructor.id] ) {
curVal = this.get(newVal[this.constructor.id])[0];
if ( can.Observe.canMakeObserve(newVal) && getId(newVal)) {
curVal = this.get(getId(newVal))[0];
if (curVal){
curVal.attr(newVal, remove)
} else {
Expand All @@ -535,12 +538,11 @@ steal('can/util', 'can/model/elements', function(can) {
}

if(remove){
var id = this.constructor.id,
existingIds = this.map(function(element) {
return element[id];
var existingIds = this.map(function(element) {
return getId(element);
}),
itemIds = items.map(function(element){
return element[id];
return getId(element);
});

can.each(existingIds, $.proxy(function(id){
Expand Down
63 changes: 63 additions & 0 deletions model/list/list_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,23 @@ test("remove", function(){
equals(res[0].id, "a1")
})

test("remove with a shadowed id", function(){
var MyModel = can.Model.extend({
id: 'foo'
},{
foo: function() {
return 'bar';
}
});

var list = new MyModel.List([
new MyModel({ foo: 'bar' }),
new MyModel({ foo: 'baz' })
]);
list.remove('bar');
equals(list.length,1,'bar was removed');
equals(list[0].attr('foo'),'baz');
});

test("list from models", function(){
var people = Person.models([{id: 1}, {id: 2}]);
Expand Down Expand Up @@ -241,6 +258,52 @@ test("attr update a list when less things come back and remove is true", functio
});


test("attr update a list with shadowed ids", function(){
var MyPerson = Person.extend({
id: function() {
return 'hi!';
}
});
var people = MyPerson.models([
{
id : 1,
name : 'Michael',
age : 20
},
{
id : 2,
name : 'Amy',
age : 80
},
{
id : 3,
name : 'Andy',
age : 1
}
]);

people.attr([
{
id : 3,
name : 'Andy',
age : 101
},
{
id : 1,
name : 'Michael',
age : 120
}], true);


equal(people.length, 2, "Removed Amy");

equal(people.attr('0.id'), 1);
equal(people.attr('0.age'), 120, "Michael's age incremented by 100 years");

equal(people.attr('1.id'), 3, "Andy is now the 2nd person in the list");
equal(people.attr('1.age'), 101, "Andy's age incremented by 100 years");
});

test("attr updates items based on id (when present), not position", function(){
var people = Person.models([
{
Expand Down
2 changes: 1 addition & 1 deletion model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ steal('can/util','can/observe', function( can ) {
modelNum = 0,
ignoreHookup = /change.observe\d+/,
getId = function( inst ) {
return inst[inst.constructor.id];
return inst.__get(inst.constructor.id);
},
// Ajax `options` generator function
ajax = function( ajaxOb, data, type, dataType, success, error ) {
Expand Down
16 changes: 16 additions & 0 deletions model/model_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ module("can/model", {

var isDojo = (typeof dojo !== "undefined");

test("shadowed id", function(){
var MyModel = can.Model({
id: 'foo'
},{
foo: function() {
return this.attr('foo');
}
});

var newModel = new MyModel({});
ok(newModel.isNew(),'new model is isNew');
var oldModel = new MyModel({foo:'bar'});
ok(!oldModel.isNew(),'old model is not new');
equals(oldModel.foo(),'bar','method can coexist with attribute');
});

test("CRUD", function(){


Expand Down

0 comments on commit 4fa3f8e

Please sign in to comment.