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

Create snapshots on save not on flush #3133

Merged
merged 1 commit into from
Jun 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions packages/ember-data/lib/system/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,7 @@ var Model = Ember.Object.extend(Ember.Evented, {
changedAttributes: function() {
var oldData = get(this, '_data');
var newData = get(this, '_attributes');
var diffData = {};
var diffData = Ember.create(null);
var prop;

for (prop in newData) {
Expand All @@ -899,11 +899,17 @@ var Model = Ember.Object.extend(Ember.Evented, {
return diffData;
},

flushChangedAttributes: function() {
this._inFlightAttributes = this._attributes;
this._attributes = Ember.create(null);
},

/**
@method adapterWillCommit
@private
*/
adapterWillCommit: function() {
this.flushChangedAttributes();
this.send('willCommit');
},

Expand Down Expand Up @@ -1052,8 +1058,6 @@ var Model = Ember.Object.extend(Ember.Evented, {
var resolver = Ember.RSVP.defer(promiseLabel);

this.store.scheduleSave(this, resolver);
this._inFlightAttributes = this._attributes;
this._attributes = Ember.create(null);

return PromiseObject.create({
promise: resolver.promise
Expand Down
29 changes: 28 additions & 1 deletion packages/ember-data/lib/system/snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ function Snapshot(record) {
this.type = record.constructor;
this.modelName = record.constructor.modelName;

this._changedAttributes = record.changedAttributes();

// The following code is here to keep backwards compatibility when accessing
// `constructor` directly.
//
Expand Down Expand Up @@ -135,7 +137,7 @@ Snapshot.prototype = {
Example

```javascript
// store.push('post', { id: 1, author: 'Tomster', title: 'Hello World' });
// store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
postSnapshot.attributes(); // => { author: 'Tomster', title: 'Ember.js rocks' }
```

Expand All @@ -146,6 +148,31 @@ Snapshot.prototype = {
return Ember.copy(this._attributes);
},

/**
Returns all changed attributes and their old and new values.

Example

```javascript
// store.push('post', { id: 1, author: 'Tomster', title: 'Ember.js rocks' });
postModel.set('title', 'Ember.js rocks!');
postSnapshot.changedAttributes(); // => { title: ['Ember.js rocks', 'Ember.js rocks!'] }
```

@method changedAttributes
@return {Object} All changed attributes of the current snapshot
*/
changedAttributes: function() {
var prop;
var changedAttributes = Ember.create(null);

for (prop in this._changedAttributes) {
changedAttributes[prop] = Ember.copy(this._changedAttributes[prop]);
}

return changedAttributes;
},

/**
Returns the current value of a belongsTo relationship.

Expand Down
18 changes: 10 additions & 8 deletions packages/ember-data/lib/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,9 @@ Store = Service.extend({
@param {Resolver} resolver
*/
scheduleSave: function(record, resolver) {
var snapshot = record._createSnapshot();
record.adapterWillCommit();
this._pendingSave.push([record, resolver]);
this._pendingSave.push([snapshot, resolver]);
once(this, 'flushPendingSave');
},

Expand All @@ -1271,8 +1272,9 @@ Store = Service.extend({
this._pendingSave = [];

forEach(pending, function(tuple) {
var record = tuple[0];
var snapshot = tuple[0];
var resolver = tuple[1];
var record = snapshot.record;
var adapter = this.adapterFor(record.constructor);
var operation;

Expand All @@ -1286,7 +1288,7 @@ Store = Service.extend({
operation = 'updateRecord';
}

resolver.resolve(_commit(adapter, this, operation, record));
resolver.resolve(_commit(adapter, this, operation, snapshot));
}, this);
},

Expand Down Expand Up @@ -2022,9 +2024,9 @@ function defaultSerializer(container) {
container.lookup('serializer:-default');
}

function _commit(adapter, store, operation, record) {
var type = record.constructor;
var snapshot = record._createSnapshot();
function _commit(adapter, store, operation, snapshot) {
var record = snapshot.record;
var type = snapshot.type;
var promise = adapter[operation](store, type, snapshot);
var serializer = serializerForAdapter(store, adapter, type);
var label = "DS: Extract and notify about " + operation + " completion of " + record;
Expand All @@ -2040,15 +2042,15 @@ function _commit(adapter, store, operation, record) {

store._adapterRun(function() {
if (adapterPayload) {
payload = serializer.extract(store, type, adapterPayload, get(record, 'id'), operation);
payload = serializer.extract(store, type, adapterPayload, get(snapshot, 'id'), operation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since snapshot is a POJO we're doing snapshot.id most places in the codebase.

}
store.didSaveRecord(record, payload);
});

return record;
}, function(reason) {
if (reason instanceof InvalidError) {
var errors = serializer.extractErrors(store, type, reason.errors, get(record, 'id'));
var errors = serializer.extractErrors(store, type, reason.errors, get(snapshot, 'id'));
store.recordWasInvalid(record, errors);
reason = new InvalidError(errors);
} else {
Expand Down
14 changes: 14 additions & 0 deletions packages/ember-data/tests/integration/snapshot-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ test("snapshot.attributes() returns a copy of all attributes for the current sna
});
});

test("snapshot.changedAttributes() returns a copy of all changed attributes for the current snapshot", function() {
expect(1);

run(function() {
var post = env.store.push('post', { id: 1, title: 'Hello World' });
post.set('title', 'Hello World!');
var snapshot = post._createSnapshot();

var changes = snapshot.changedAttributes();

deepEqual(changes, { title: ['Hello World', 'Hello World!'] }, 'changed attributes are returned correctly');
});
});

test("snapshot.belongsTo() returns undefined if relationship is undefined", function() {
expect(1);

Expand Down