Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can.Model with attributes that are models gets corrupted when you call attr() #141

Closed
wants to merge 8 commits into from
5 changes: 4 additions & 1 deletion model/list/list.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
steal('can/util', 'can/model/elements', function(can) {
steal('can/util', 'can/observe/elements', function(can) {

var getArgs = function( args ) {
if ( args[0] && (can.isArray(args[0])) ) {
Expand Down Expand Up @@ -540,6 +540,9 @@ steal('can/util', 'can/model/elements', function(can) {

if (itemsNotInList.length > 0){
//splice everything onto end of list so as not to trigger change events for each push
if (this.constructor.namespace){
itemsNotInList = can.makeArray(this.constructor.namespace.models(itemsNotInList));
}
this.splice.apply(this, [this.length, 0].concat(itemsNotInList));
}

Expand Down
92 changes: 91 additions & 1 deletion observe/attributes/attributes_test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
steal('can/util', 'can/observe/attributes', function(can) {
steal('can/util', 'can/model', 'can/model/list', 'can/observe/attributes', function(can) {

module("can/observe/attributes");

Expand Down Expand Up @@ -167,6 +167,96 @@ test("defaults", function(){
equals(link.attr('rupees'), 255);
});

test("nested model attr", function(){
can.Model('NestedAttrTest.User', {}, {});

can.Model('NestedAttrTest.Task', {
attributes : {
owner : "NestedAttrTest.User.model"
}
}, {});


can.Model('NestedAttrTest.Project',{
attributes : {
creator : "NestedAttrTest.User.model"
}
}, {});

var michael = NestedAttrTest.User.model({ id : 17, name : 'Michael'});
var amy = NestedAttrTest.User.model({ id : 29, name : 'Amy'});

// add bindings so the objects get stored in the User.store
michael.bind('foo', function(){});
amy.bind('foo', function(){});

var task = NestedAttrTest.Task.model({
id : 1,
name : "Do it!",
owner : {id : 17}
});

var project = NestedAttrTest.Project.model({
id : 1,
name : "Get Things Done",
creator : {id : 17}
});

task.bind('foo', function(){});
project.bind('foo', function(){});

equal(task.attr('owner.name'), 'Michael', 'owner hash correctly modeled');
equal(project.attr('creator.name'), 'Michael', 'creator hash correctly modeled');

task.attr({ owner : { id : 29, name : 'Amy'}});
equal(task.attr('owner.name'), 'Amy', 'Task correctly updated to Amy user model');
equal(task.attr('owner.id'), 29, 'Task correctly updated to Amy user model');

equal(project.attr('creator.name'), 'Michael', 'Project creator should still be Michael');
equal(project.attr('creator.id'), 17, 'Project creator should still be Michael');
equal(NestedAttrTest.User.store[17].id, 17, "The model store should still have Michael associated by his id");
});

test("attr() should respect convert functions for lists when updating", function(){
can.Model('ListTest.User', {}, {});
can.Model.List('ListTest.User.List', {}, {});

can.Model('ListTest.Task', {
attributes : {
project : "ListTest.Project.model"
}
}, {});

can.Model('ListTest.Project',{
attributes : {
members : "ListTest.User.models"
}
}, {});

var task = ListTest.Task.model({
id : 1,
name : "Do it!",
project : {
id : 789,
name : "Get stuff done",
members : []
}
});

equal(task.project.members instanceof ListTest.User.List, true, "the list is a User List");

task.attr({
id : 1,
project : {
id : 789,
members: [{ id : 72, name : "Andy"}, { id : 74, name : "Michael"}]
}
});

equal(task.project.members instanceof ListTest.User.List, true, "the list is a User List");
equal(task.project.members.length, 2, "The members were added");
equal(task.project.members[0] instanceof ListTest.User, true, "The members was converted to a model object");
equal(task.project.members[1] instanceof ListTest.User, true, "The user was converted to a model object");
});

})();
2 changes: 1 addition & 1 deletion observe/observe.js
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ steal('can/util','can/construct', function(can, Construct) {
remove && self.removeAttr(prop);
return;
}
if ( canMakeObserve(curVal) && canMakeObserve(newVal) && curVal.attr ) {
if ( canMakeObserve(curVal) && canMakeObserve(newVal) && curVal.attr && (curVal[this.constructor.id] == newVal[this.constructor.id]) ) {
curVal.attr(newVal, remove)
} else if ( curVal != newVal ) {
self._set(prop, newVal)
Expand Down