diff --git a/addon/serializers/firebase.js b/addon/serializers/firebase.js index 31e1161d..732fe3a7 100644 --- a/addon/serializers/firebase.js +++ b/addon/serializers/firebase.js @@ -9,6 +9,25 @@ import assign from 'lodash/object/assign'; export default DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, { isNewSerializerAPI: true, + /** + * Firebase does not send null values, it omits the key altogether. This nullifies omitted + * properties so that property deletions sync correctly. + * + * @override + */ + extractAttributes: function (modelClass, resourceHash) { + var attributes = this._super(modelClass, resourceHash); + + // nullify omitted attributes + modelClass.eachAttribute(function (key) { + if (!attributes.hasOwnProperty(key)) { + attributes[key] = null; + } + }); + + return attributes; + }, + /** * @override */ diff --git a/changelog.txt b/changelog.txt index e69de29b..796bd7ab 100644 --- a/changelog.txt +++ b/changelog.txt @@ -0,0 +1 @@ +fixed - Deleted model properties were not synchronizing. diff --git a/tests/integration/updates-from-server-test.js b/tests/integration/updates-from-server-test.js index ede3514e..c23ed793 100644 --- a/tests/integration/updates-from-server-test.js +++ b/tests/integration/updates-from-server-test.js @@ -60,22 +60,30 @@ describe('Integration: FirebaseAdapter - Updates from server', function() { }); describe('A record coming from find', function() { - var newPost; + var reference, newPost; beforeEach(function(done) { - var reference = adapter._ref; + reference = adapter._ref; Ember.run(function() { store.findRecord('post', 'post_1').then(function(post) { newPost = post; - reference.child('posts/post_1/body').set('Updated', function() { - done(); - }); + done(); }); }); }); - it('receives server updates correctly', function() { - expect(newPost.get('body')).to.equal('Updated', 'property should change'); + it('receives server updates correctly', function(done) { + reference.child('posts/post_1/body').set('Updated', function() { + expect(newPost.get('body')).to.equal('Updated', 'property should change'); + done(); + }); + }); + + it('receives server property deletions correctly', function(done) { + reference.child('posts/post_1/body').remove(function() { + expect(newPost.get('body')).to.equal(null, 'property should be deleted'); + done(); + }); }); it('has the correct .ref()', function() { diff --git a/tests/unit/serializers/firebase-test.js b/tests/unit/serializers/firebase-test.js index 28ca7e77..7c12c018 100644 --- a/tests/unit/serializers/firebase-test.js +++ b/tests/unit/serializers/firebase-test.js @@ -427,7 +427,8 @@ describeModule( expect(json.included).to.have.length(1); expect(json.included[0].attributes).to.deep.equal({ - firstName: 'Adam' + firstName: 'Adam', + created: null }); expect(json.included[0].id).to.equal('aputinski'); @@ -486,7 +487,8 @@ describeModule( expect(json.included).to.have.length(1); expect(json.included[0].attributes).to.deep.equal({ - firstName: 'Adam' + firstName: 'Adam', + created: null }); expect(json.included[0].id).to.equal('aputinski');