Permalink
Browse files

Close #141 refactor attribute and property handling on observes.

  • Loading branch information...
1 parent 816f182 commit f9896d928d7547b63d625eeae1badd22e3ab8068 @imjoshdean imjoshdean committed Nov 8, 2012
Showing with 132 additions and 7 deletions.
  1. +4 −1 model/list/list.js
  2. +92 −1 observe/attributes/attributes_test.js
  3. +16 −5 observe/observe.js
  4. +20 −0 observe/observe_test.js
View
@@ -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])) ) {
@@ -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));
}
@@ -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");
@@ -167,6 +167,97 @@ 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");
+});
})();
View
@@ -724,12 +724,23 @@ steal('can/util','can/construct', function(can) {
remove && self.removeAttr(prop);
return;
}
- if ( canMakeObserve(curVal) && canMakeObserve(newVal) && curVal.attr ) {
- curVal.attr(newVal, remove)
- } else if ( curVal != newVal ) {
- self._set(prop, newVal)
- } else {
+ if ( self.__convert ) {
+ newVal = self.__convert(prop, newVal);
+ }
+
+ if ( curVal !== newVal ) {
+ if ( curVal instanceof can.Observe && newVal instanceof can.Observe ) {
+ unhookup([curVal], self._cid);
+ }
+ if ( newVal instanceof can.Observe ) {
+ self._set(prop, newVal)
+ }
+ else if ( canMakeObserve(curVal) && canMakeObserve(newVal) ) {
+ curVal.attr(newVal, remove)
+ } else if ( curVal != newVal ) {
+ self._set(prop, newVal)
+ }
}
delete props[prop];
})
View
@@ -458,5 +458,25 @@ test("startBatch and stopBatch and changed event", function(){
});
+test("nested observe attr", function() {
+ var person1 = new can.Observe( { name: {first: 'Josh' } } ),
+ person2 = new can.Observe( { name: {first: 'Justin', last: 'Meyer' } } ),
+ count = 0;
+
+ person1.bind("change", function(ev, attr, how, val, old){
+ equals(count, 0, 'change called once')
+ count++;
+ equals(attr, 'name');
+ equals(val.attr('first'), 'Justin');
+ equals(val.attr('last'), 'Meyer');
+ })
+
+ person1.attr('name', person2.attr('name'));
+
+ // Attempt to set the name attribute again, should not
+ // cause any triggers.
+ person1.attr('name', person2.attr('name'));
+})
+
})();

0 comments on commit f9896d9

Please sign in to comment.