diff --git a/bower.json b/bower.json index b52e80f..67728d4 100644 --- a/bower.json +++ b/bower.json @@ -1,10 +1,11 @@ { "name": "ember-model", - "version": "0.0.14", + "version": "0.0.15", "main": "ember-model.js", "dependencies": { - "ember": "~1.11" + "ember": "~1.10" }, + "swrve_notice": "DOWNGRADED_EMBER_VERSION_FROM_1.11_TO_MATCH_OURS", "devDependencies": { "qunit": "~1.11" }, diff --git a/ember-model.js b/ember-model.js index 36c8c4d..143dca8 100644 --- a/ember-model.js +++ b/ember-model.js @@ -1,6 +1,6 @@ (function() { -var VERSION = '0.0.14'; +var VERSION = '0.0.15'; if (Ember.libraries) { Ember.libraries.register('Ember Model', VERSION); @@ -630,7 +630,7 @@ Ember.Model = Ember.Object.extend(Ember.Evented, { var relationships = this.constructor._relationships || [], meta = Ember.meta(this), relationshipKey, relationship, relationshipMeta, relationshipData, relationshipType; for (var i = 0, l = relationships.length; i < l; i++) { relationshipKey = relationships[i]; - relationship = meta.descs[relationshipKey]; + relationship = (meta.descs || this)[relationshipKey]; relationshipMeta = relationship.meta(); if (relationshipMeta.options.embedded) { @@ -1256,11 +1256,14 @@ Ember.Model.reopenClass({ // FIXME findFromCacheOrLoad: function(data, container) { var record; - if (!data[get(this, 'primaryKey')]) { + // SWRVE CHANGES + var primaryKeyValue = data[get(this, 'primaryKey')]; + if (!primaryKeyValue) { record = this.create({isLoaded: false, container: container}); } else { - record = this.cachedRecordForId(data[get(this, 'primaryKey')], container); + record = this.cachedRecordForId(primaryKeyValue, container); } + // END OF SWRVE CHANGES // set(record, 'data', data); record.load(data[get(this, 'primaryKey')], data); return record; diff --git a/package.json b/package.json index 32387e5..07c9d25 100644 --- a/package.json +++ b/package.json @@ -32,5 +32,5 @@ "grunt-contrib-watch": "~0.4.4", "grunt-ember-s3": "~1.0.2" }, - "version": "0.0.11" + "version": "0.0.15" } diff --git a/packages/ember-model/lib/has_many.js b/packages/ember-model/lib/has_many.js index 9756a3b..c3c935c 100644 --- a/packages/ember-model/lib/has_many.js +++ b/packages/ember-model/lib/has_many.js @@ -28,7 +28,14 @@ Ember.hasMany = function(type, options) { var key = options.key || propertyKey; if (arguments.length > 1) { - return existingArray.setObjects(newContentArray); + // SWRVE CHANGES + // Check if the arrays are the same, + // otherwise observers are executed for nothing! + if (!Ember.isEqual(newContentArray, existingArray)) { + // END OF SWRVE CHANGES + return existingArray.setObjects(newContentArray); + } + return existingArray; } else { return this.getHasMany(key, type, meta, this.container); } diff --git a/packages/ember-model/lib/has_many_array.js b/packages/ember-model/lib/has_many_array.js index 0e8d80d..28564dc 100644 --- a/packages/ember-model/lib/has_many_array.js +++ b/packages/ember-model/lib/has_many_array.js @@ -123,11 +123,24 @@ Ember.ManyArray = Ember.RecordArray.extend({ }, load: function(content) { - Ember.setProperties(this, { - content: content, - originalContent: content.slice() - }); + // SWRVE CHANGES + // Check if the new items are the same as the current ones + // Otherwise observers are executed for nothing! + var currentContent = get(this, 'content'); + var mustUpdateCollection = content.length !== currentContent.length; + for (var i = 0, l = content.length; i < l && !mustUpdateCollection; i++) { + var existingItem = currentContent[i]; + var newItem = content[i]; + mustUpdateCollection = newItem !== existingItem; + } + if (mustUpdateCollection) { + Ember.setProperties(this, { + content: content, + originalContent: content.slice() + }); + } set(this, '_modifiedRecords', []); + // END OF SWRVE CHANGES }, revert: function() { diff --git a/packages/ember-model/lib/version.js b/packages/ember-model/lib/version.js index 3e864cb..c1c0098 100644 --- a/packages/ember-model/lib/version.js +++ b/packages/ember-model/lib/version.js @@ -1,4 +1,4 @@ -var VERSION = '0.0.14'; +var VERSION = '0.0.15'; if (Ember.libraries) { Ember.libraries.register('Ember Model', VERSION); diff --git a/packages/ember-model/tests/has_many/embedded_objects_load_test.js b/packages/ember-model/tests/has_many/embedded_objects_load_test.js index a0c678c..4092a1a 100644 --- a/packages/ember-model/tests/has_many/embedded_objects_load_test.js +++ b/packages/ember-model/tests/has_many/embedded_objects_load_test.js @@ -115,3 +115,59 @@ test("loading embedded data into a parent with deleted children deletes the chil equal(post.get('comments.length'), 1); equal(post.get('comments.firstObject.body'), 'new'); }); + +// SWRVE CHANGES +test("loading collections with same element twice does not trigger observers", function() { + expect(4); + var json = { + id: 1, + title: 'foo', + comments: [{ + id: 1, + text: 'helo' + }] + }; + + var Comment = Ember.Model.extend({ + id: attr(), + text: attr() + }); + Comment.adapter = Ember.RESTAdapter.create(); + Comment.url = '/comments'; + + var Article = Ember.Model.extend({ + title: attr(), + comments: Ember.hasMany(Comment, { key: 'comments', embedded: true }), + + commentsChangeCounter: 0, + commentsChanged: function() { + this.incrementProperty('commentsChangeCounter'); + }.observes('comments.@each') + }); + Article.adapter = Ember.RESTAdapter.create(); + Article.url = '/articles'; + Article.adapter._ajax = function() { + return new Ember.RSVP.Promise(function(resolve) { + resolve(json); + }); + }; + + var article = Article.create(); + Ember.run(article, article.load, json.id, json); + // Force collection to be taken into account (_registerHasManyArray) + var comments = article.get('comments'); + equal(article.get('commentsChangeCounter'), 0, "Inital load didn't triggered observers"); + var json2 = { + id: 1, + title: 'foo', + comments: [{ + id: 1, + text: 'helo here' // <- updated + }] + }; + Ember.run(article, article.load, json.id, json2); + equal(article.get('commentsChangeCounter'), 0, "Load with the same collection didn't triggered observers"); + equal(comments.get('isDirty'), false, "comments should not be dirty"); + deepEqual(Ember.run(comments, comments.mapProperty, 'text'), ['helo here']); +}); +// END OF SWRVE CHANGES diff --git a/packages/ember-model/tests/has_many/manipulation_test.js b/packages/ember-model/tests/has_many/manipulation_test.js index 51e6339..2f168fc 100644 --- a/packages/ember-model/tests/has_many/manipulation_test.js +++ b/packages/ember-model/tests/has_many/manipulation_test.js @@ -3,6 +3,7 @@ var attr = Ember.attr; module("Ember.HasManyArray - manipulation"); test("pushing record without an id adds a reference to the content", function() { + expect(3); var json = { id: 1, title: 'foo', @@ -42,6 +43,7 @@ test("pushing record without an id adds a reference to the content", function() }); test('adding and reverting an existing record to a many array', function () { + expect(6); var json = { id: 1, title: 'foo', @@ -86,6 +88,7 @@ test('adding and reverting an existing record to a many array', function () { }); test('adding and reverting a new record to a many array', function () { + expect(6); var json = { id: 1, title: 'foo', @@ -128,6 +131,7 @@ test('adding and reverting a new record to a many array', function () { }); test("removing a record from the many array", function() { + expect(4); var json = { id: 1, title: 'foo', @@ -169,6 +173,7 @@ test("removing a record from the many array", function() { }); test("setting a has many array with empty array", function() { + expect(5); var json = { id: 1, title: 'foo', @@ -208,6 +213,7 @@ test("setting a has many array with empty array", function() { }); test("setting a has many array with item array", function() { + expect(5); var json = { id: 1, title: 'foo', @@ -247,6 +253,7 @@ test("setting a has many array with item array", function() { }); test("setting a hasMany array with setObjects", function() { + expect(5); var json = { id: 1, title: 'foo', @@ -283,4 +290,52 @@ test("setting a hasMany array with setObjects", function() { equal(article.get('comments.length'), 3, "should be 3 comments after revert"); equal(article.get('comments.isDirty'), false, "should not be dirty after revert"); -}); \ No newline at end of file +}); + +// SWRVE CHANGES +test("setting a has many array with the same array should not trigger its observers", function() { + expect(7); + var json = { + id: 1, + title: 'foo', + comments: [1, 2, 3] + }; + + var Comment = Ember.Model.extend({ + text: attr() + }); + + var Article = Ember.Model.extend({ + title: attr(), + + comments: Ember.hasMany(Comment, { key: 'comments' }), + + commentsChangeCounter: 0, + commentsChanged: function() { + this.incrementProperty('commentsChangeCounter'); + }.observes('comments.@each') + }); + + Comment.adapter = Ember.FixtureAdapter.create(); + Comment.FIXTURES = [ + {id: 1, text: 'uno'}, + {id: 2, text: 'dos'}, + {id: 3, text: 'tres'} + ]; + + var article = Article.create(); + Ember.run(article, article.load, json.id, json); + + equal(article.get('comments.length'), 3, "should be 3 comments"); + + article.set('comments', article.get('comments')); + equal(article.get('comments.length'), 3, "should still be 3 comments"); + equal(article.get('comments.isDirty'), false, "comments should not be dirty"); + equal(article.get('commentsChangeCounter'), 0, "comment observers should not fire"); + + article.set('comments', [Comment.find(3)]); + equal(article.get('comments.length'), 1, "should be 1 comment after set"); + equal(article.get('comments.isDirty'), true, "comments should be dirty after set"); + equal(article.get('commentsChangeCounter'), 1, "comment observers should have fired 1 time"); +}); +// END OF SWRVE CHANGES \ No newline at end of file diff --git a/packages/ember-model/tests/model_test.js b/packages/ember-model/tests/model_test.js index 7415f24..371dd7a 100644 --- a/packages/ember-model/tests/model_test.js +++ b/packages/ember-model/tests/model_test.js @@ -651,9 +651,9 @@ test("toJSON works with string names", function() { author: Ember.belongsTo('author', { key: 'author' }) }); - App.registry.register('model:comment', Comment); - App.registry.register('model:author', Author); - App.registry.register('model:article', Article); + App.__container__.register('model:comment', Comment); + App.__container__.register('model:author', Author); + App.__container__.register('model:article', Article); var articleData = { id: 1, diff --git a/packages/ember-model/tests/record_array_test.js b/packages/ember-model/tests/record_array_test.js index dae6178..3049b86 100644 --- a/packages/ember-model/tests/record_array_test.js +++ b/packages/ember-model/tests/record_array_test.js @@ -18,7 +18,7 @@ module("Ember.RecordArray", { {id: 2, name: 'Stefan'}, {id: 3, name: 'Kris'} ]; - container = new Ember.Registry().container(); + container = new Ember.Container(); }, teardown: function() { } }); diff --git a/packages/ember-model/tests/store_test.js b/packages/ember-model/tests/store_test.js index cd4d1f7..17ce1a8 100644 --- a/packages/ember-model/tests/store_test.js +++ b/packages/ember-model/tests/store_test.js @@ -1,9 +1,8 @@ -var TestModel, EmbeddedModel, UUIDModel, store, registry, container, App; +var TestModel, EmbeddedModel, UUIDModel, store, container, App; module("Ember.Model.Store", { setup: function() { - registry = new Ember.Registry(); - container = registry.container(); + container = new Ember.Container(); store = Ember.Model.Store.create({container: container}); TestModel = Ember.Model.extend({ @@ -61,10 +60,10 @@ module("Ember.Model.Store", { }); EmbeddedModel.adapter = Ember.FixtureAdapter.create({}); - registry.register('model:test', TestModel); - registry.register('model:embedded', EmbeddedModel); - registry.register('model:uuid', UUIDModel); - registry.register('store:main', Ember.Model.Store); + container.register('model:test', TestModel); + container.register('model:embedded', EmbeddedModel); + container.register('model:uuid', UUIDModel); + container.register('store:main', Ember.Model.Store); } }); @@ -172,16 +171,16 @@ test("store.adapterFor(type) returns klass.adapter first", function() { test("store.adapterFor(type) returns type adapter if no klass.adapter", function() { TestModel.adapter = undefined; - registry.register('adapter:test', Ember.FixtureAdapter); - registry.register('adapter:application', null); + container.register('adapter:test', Ember.FixtureAdapter); + container.register('adapter:application', null); var adapter = Ember.run(store, store.adapterFor, 'test'); ok(adapter instanceof Ember.FixtureAdapter); }); test("store.adapterFor(type) returns application adapter if no klass.adapter or type adapter", function() { TestModel.adapter = undefined; - registry.register('adapter:test', null); - registry.register('adapter:application', Ember.FixtureAdapter); + container.register('adapter:test', null); + container.register('adapter:application', Ember.FixtureAdapter); var adapter = Ember.run(store, store.adapterFor, 'test'); ok(adapter instanceof Ember.FixtureAdapter); }); @@ -189,9 +188,9 @@ test("store.adapterFor(type) returns application adapter if no klass.adapter or test("store.adapterFor(type) defaults to RESTAdapter if no adapter specified", function() { TestModel.adapter = undefined; - registry.register('adapter:test', null); - registry.register('adapter:application', null); - registry.register('adapter:REST', Ember.RESTAdapter); + container.register('adapter:test', null); + container.register('adapter:application', null); + container.register('adapter:REST', Ember.RESTAdapter); var adapter = Ember.run(store, store.adapterFor, 'test'); ok(adapter instanceof Ember.RESTAdapter); }); @@ -200,8 +199,8 @@ test("store.find(type) records use application adapter if no klass.adapter or ty expect(3); TestModel.adapter = undefined; EmbeddedModel.adapter = undefined; - registry.register('adapter:test', null); - registry.register('adapter:application', Ember.FixtureAdapter); + container.register('adapter:test', null); + container.register('adapter:application', Ember.FixtureAdapter); var promise = Ember.run(store, store.find, 'test','a'); diff --git a/tests/runner.html.tmpl b/tests/runner.html.tmpl index e2b763e..f1ce223 100644 --- a/tests/runner.html.tmpl +++ b/tests/runner.html.tmpl @@ -2,7 +2,7 @@
-