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

Initial implementation of the Snapshot API #2623

Merged
merged 4 commits into from
Feb 13, 2015
Merged

Conversation

wecc
Copy link
Contributor

@wecc wecc commented Dec 23, 2014

This is a first stab at the new Snapshot API, serializer.serialize() now receives a Snapshot instead of a record instance.

  • Caching - Right now, attributes are cached eagerly (on instantiation) and relationships are cached on first access. Is this the design we want?
  • snapshot.belongsTo() - Returns a new snapshot (with at least an ID) or undefined. Is this what we want or should we always return a new snapshot?
  • snapshot.hasMany() - Always returns an array.
  • snapshot.get() deprecated - To only use attr(), belongsTo() and hasMany() would require some work in serializers. Should that be done in the scope of this PR or separately? Done in this PR.

[@sly7-7]: Just to clean issues when that awesome work is merged:
Closes #2551, Fixes #2385, Fixes #2508, Closes #1491

Fixes #2750, Closes #2739

@private
*/
var Snapshot = function(record) {
var attributes = Object.create(null);
Copy link
Member

Choose a reason for hiding this comment

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

Ember.create to get the polyfil

@fivetanley
Copy link
Member

super cool!

@wecc wecc force-pushed the snapshots branch 2 times, most recently from e7bf3b9 to 4e26221 Compare December 24, 2014 08:44
@stefanpenner
Copy link
Member

Ah if it's an ordered set forEach is perfect

@sly7-7
Copy link
Contributor

sly7-7 commented Dec 24, 2014

I think there is a problem with the way of relationships are built. Since they are lazily cached, there may be some inconsistencies if for example a snapshot is created, its relationships are accessed, and in the meantime the record's relationships are modified. Unless I'm wrong could lead to wrong snapshot's relationships values.

@wecc wecc mentioned this pull request Dec 28, 2014
28 tasks
@@ -936,6 +937,10 @@ var Model = Ember.Object.extend(Ember.Evented, {
this._notifyProperties(dirtyKeys);
},

snapshot: function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Underscore this, add doc @Private

@wecc wecc force-pushed the snapshots branch 2 times, most recently from 783db24 to 6a8b76a Compare December 30, 2014 22:35
if (relationship && relationship.relationshipMeta.kind === 'hasMany') {
return this.hasMany(keyName);
}
return this.attr(keyName);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Check if keyName is attr, if not, pass to this.record.get()

@igorT
Copy link
Member

igorT commented Dec 31, 2014

snapshot.hasMany('foo', { ids: true })

@wecc wecc force-pushed the snapshots branch 3 times, most recently from bb2eea4 to f4957ce Compare January 4, 2015 18:34

var get = Ember.get;

var hasPropertyAccessors = Ember.__loader.require('ember-metal/platform')['hasPropertyAccessors'];
Copy link
Member

Choose a reason for hiding this comment

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

This is exported by Ember as Ember.platform.hasPropertyAccessors since at least 1.8.

https://github.com/emberjs/ember.js/blob/v1.8.1/packages/ember-metal/lib/main.js#L183-L186

@wecc wecc force-pushed the snapshots branch 3 times, most recently from 7e89904 to c293f30 Compare January 5, 2015 22:29
@tomdale
Copy link
Member

tomdale commented Jan 26, 2015

@knownasilya As @wecc described, the high order bit for me is that a snapshot represents the frozen state of a record at a particular moment in time. As we push everything towards being all-async all the time, you want to get a way to examine the current state of that record in the moment without triggering all sorts of side-effects, like loading relationships.

@knownasilya
Copy link
Contributor

Thanks for the clarification @wecc and @tomdale. It sure sounds like a useful and needed API, especially in the async scenario. I've struggled numerous times trying to get state without triggering any observers/cps in complicated scenarios, and it's a battle.

@sly7-7
Copy link
Contributor

sly7-7 commented Jan 26, 2015

@tomdale @wecc From what I understand from the code, I think there are still inconsistencies in the implementation. Since the relationships are lazy and the attributes are eager, actually when you create a snapshot, and the access its data, I think problems can occur if the relationships of the underlying are changed before the snapshot's ones are accessed. Though I just may be completely wrong.

@tomdale
Copy link
Member

tomdale commented Jan 26, 2015

@sly7-7 You're absolutely correct. We discussed this at length and decided that you need to pre-emptively access the snapshot's relationships if you want to freeze them at that moment in time. If we eagerly snapshot all relationships as well as attributes, we may have to create thousands of snapshots that the user never needs. Definitely open to other suggestions here, because it's going to trip people up. But I don't know how to avoid making it easy to snapshot the entire object graph otherwise.

@bakura10
Copy link
Contributor

bakura10 commented Feb 1, 2015

I'm not sure to completely understand this feature. Can it be used to create "forked models" (à la EPF), so hat modifications are applied locally, and then saved independently (to avoid the very famous binding problem where properties are updated visually while the model is not saved yet)

@tomdale
Copy link
Member

tomdale commented Feb 1, 2015

@bakura10 It is not that complex. It simply, at snapshot time, loops over all of the attributes of a model and copies their current values over into an immutable hash, giving you a "snapshot in time" of the state of that model.

@thomasvanlankveld
Copy link

If this does what I think it will do, it's going to make me very very happy :)

@method id
@return {String} The ID of the snapshot's record
*/
id: function() {
Copy link
Member

Choose a reason for hiding this comment

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

I'm nervous because now if you do record.id it will return the id of the record. This could break serializers that are relying on this behavior.

@wecc
Copy link
Contributor Author

wecc commented Feb 13, 2015

Rebased, merge conflicts fixed.

```

@method id
@return {String} The ID of the snapshot's record
Copy link
Member

Choose a reason for hiding this comment

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

 @property id
 @type {String}

bmac added a commit that referenced this pull request Feb 13, 2015
Initial implementation of the Snapshot API
@bmac bmac merged commit 64ccb96 into emberjs:master Feb 13, 2015
@runspired runspired added 🏷️ feat This PR introduces a new feature and removed Feature labels Sep 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment