-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial implementation of the Snapshot API
- Loading branch information
Showing
5 changed files
with
312 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
@module ember-data | ||
*/ | ||
|
||
var get = Ember.get; | ||
|
||
/** | ||
@class Snapshot | ||
@namespace DS | ||
@private | ||
*/ | ||
function Snapshot(record) { | ||
var attributes = Ember.create(null); | ||
|
||
attributes['id'] = get(record, 'id'); | ||
|
||
record.eachAttribute(function(keyName) { | ||
attributes[keyName] = get(record, keyName); | ||
}); | ||
|
||
this.record = record; | ||
|
||
this.attributes = attributes; | ||
this.belongsToRelationships = Ember.create(null); | ||
this.hasManyRelationships = Ember.create(null); | ||
} | ||
|
||
Snapshot.prototype = { | ||
constructor: Snapshot, | ||
|
||
/** | ||
@method attr | ||
@param {string} keyName | ||
@return {Object} The attribute value or undefined | ||
*/ | ||
attr: function(keyName) { | ||
if (keyName in this.attributes) { | ||
return this.attributes[keyName]; | ||
} | ||
throw new Ember.Error("Model '" + Ember.inspect(this.record) + "' has no attribute named '" + keyName + "' defined."); | ||
}, | ||
|
||
/** | ||
@method belongsTo | ||
@param {string} keyName | ||
@return {DS.Snapshot} A snapshot of a belongsTo relationship | ||
*/ | ||
belongsTo: function(keyName) { | ||
if (keyName in this.belongsToRelationships) { | ||
return this.belongsToRelationships[keyName]; | ||
} | ||
|
||
var relationship = this.record._relationships[keyName]; | ||
var snapshot; | ||
|
||
if (relationship && relationship.relationshipMeta.kind === 'belongsTo') { | ||
var inverseRecord = get(relationship, 'inverseRecord'); | ||
if (inverseRecord) { | ||
snapshot = inverseRecord.snapshot(); | ||
} | ||
return this.belongsToRelationships[keyName] = snapshot; | ||
} | ||
|
||
throw new Ember.Error("Model '" + Ember.inspect(this.record) + "' has no belongsTo relationship named '" + keyName + "' defined."); | ||
}, | ||
|
||
/** | ||
@method hasMany | ||
@param {string} keyName | ||
@return {Array} An array of snapshots of a hasMany relationship | ||
*/ | ||
hasMany: function(keyName) { | ||
if (keyName in this.hasManyRelationships) { | ||
return this.hasManyRelationships[keyName]; | ||
} | ||
|
||
var relationship = this.record._relationships[keyName]; | ||
var snapshots = []; | ||
|
||
if (relationship && relationship.relationshipMeta.kind === 'hasMany') { | ||
var members = get(relationship, 'members'); | ||
members.forEach(function(member) { | ||
snapshots.pushObject(member.snapshot()); | ||
}); | ||
return this.hasManyRelationships[keyName] = snapshots; | ||
} | ||
|
||
throw new Ember.Error("Model '" + Ember.inspect(this.record) + "' has no hasMany relationship named '" + keyName + "' defined."); | ||
}, | ||
|
||
/** | ||
@method eachAttribute | ||
@param {Function} callback the callback to execute | ||
@param {Object} [binding] the value to which the callback's `this` should be bound | ||
*/ | ||
eachAttribute: function(callback, binding) { | ||
this.record.eachAttribute(callback, binding); | ||
}, | ||
|
||
/** | ||
@method eachRelationship | ||
@param {Function} callback the callback to execute | ||
@param {Object} [binding] the value to which the callback's `this` should be bound | ||
*/ | ||
eachRelationship: function(callback, binding) { | ||
this.record.eachRelationship(callback, binding); | ||
}, | ||
|
||
/** | ||
@method get | ||
@param {string} keyName | ||
@return {Object} The property value | ||
@deprecated Use [attr](#method_attr), [belongsTo](#method_belongsTo) or [hasMany](#method_hasMany) instead | ||
*/ | ||
get: function(keyName) { | ||
Ember.deprecate('Using DS.Snapshot.get() is deprecated. Use .attr(), .belongsTo() or .hasMany() instead.'); | ||
|
||
var relationship = this.record._relationships[keyName]; | ||
|
||
if (relationship && relationship.relationshipMeta.kind === 'belongsTo') { | ||
return this.belongsTo(keyName); | ||
} | ||
if (relationship && relationship.relationshipMeta.kind === 'hasMany') { | ||
return this.hasMany(keyName); | ||
} | ||
return this.attr(keyName); | ||
}, | ||
|
||
/** | ||
@method unknownProperty | ||
@param {string} keyName | ||
@return {Object} The property value | ||
@deprecated Use [attr](#method_attr), [belongsTo](#method_belongsTo) or [hasMany](#method_hasMany) instead | ||
*/ | ||
unknownProperty: function(keyName) { | ||
return this.get(keyName); | ||
} | ||
}; | ||
|
||
export default Snapshot; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
var run = Ember.run; | ||
var env, Post, Comment; | ||
|
||
module("integration/snapshot - DS.Snapshot", { | ||
setup: function() { | ||
Post = DS.Model.extend({ | ||
title: DS.attr(), | ||
comments: DS.hasMany() | ||
}); | ||
Comment = DS.Model.extend({ | ||
body: DS.attr(), | ||
post: DS.belongsTo() | ||
}); | ||
|
||
env = setupStore({ | ||
post: Post, | ||
comment: Comment | ||
}); | ||
}, | ||
|
||
teardown: function() { | ||
run(function(){ | ||
env.store.destroy(); | ||
}); | ||
} | ||
}); | ||
|
||
test("record.snapshot() returns a snapshot", function() { | ||
expect(1); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World' }); | ||
var snapshot = post.snapshot(); | ||
|
||
ok(snapshot instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot'); | ||
}); | ||
}); | ||
|
||
test("snapshot attr() does not change when record changes", function() { | ||
expect(2); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World' }); | ||
var snapshot = post.snapshot(); | ||
|
||
equal(snapshot.attr('title'), 'Hello World', 'snapshot title is correct'); | ||
post.set('title', 'Tomster'); | ||
equal(snapshot.attr('title'), 'Hello World', 'snapshot title is still correct'); | ||
}); | ||
}); | ||
|
||
test("snapshot belongTo() returns undefined if relationship is undefined", function() { | ||
expect(1); | ||
|
||
run(function() { | ||
var comment = env.store.push('comment', { id: 1, body: 'This is comment' }); | ||
var snapshot = comment.snapshot(); | ||
var relationship = snapshot.belongsTo('post'); | ||
|
||
equal(relationship, undefined, 'relationship is undefined'); | ||
}); | ||
}); | ||
|
||
test("snapshot belongTo() returns a snapshot if relationship is set", function() { | ||
expect(3); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World' }); | ||
var comment = env.store.push('comment', { id: 2, body: 'This is comment', post: 1 }); | ||
var snapshot = comment.snapshot(); | ||
var relationship = snapshot.belongsTo('post'); | ||
|
||
ok(relationship instanceof DS.Snapshot, 'snapshot is an instance of DS.Snapshot') | ||
equal(relationship.attr('id'), 1, 'post id is correct'); | ||
equal(relationship.attr('title'), 'Hello World', 'post title is correct'); | ||
}); | ||
}); | ||
|
||
test("snapshot hasMany() returns empty array if relationship is undefined", function() { | ||
expect(2); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World' }); | ||
var snapshot = post.snapshot(); | ||
var relationship = snapshot.hasMany('comments'); | ||
|
||
ok(relationship instanceof Array, 'relationship is an instance of Array'); | ||
equal(relationship.length, 0, 'relationship is empty'); | ||
}); | ||
}); | ||
|
||
test("snapshot hasMany() returns array of snapshots if relationship is set", function() { | ||
expect(5); | ||
|
||
run(function() { | ||
var comment1 = env.store.push('comment', { id: 1, body: 'This is the first comment' }); | ||
var comment2 = env.store.push('comment', { id: 2, body: 'This is the second comment' }); | ||
var post = env.store.push('post', { id: 3, title: 'Hello World', comments: [1, 2] }); | ||
var snapshot = post.snapshot(); | ||
var relationship = snapshot.hasMany('comments'); | ||
|
||
ok(relationship instanceof Array, 'relationship is an instance of Array'); | ||
equal(relationship.length, 2, 'relationship has two items'); | ||
|
||
var relationship1 = relationship[0]; | ||
var relationship2 = relationship[1]; | ||
|
||
ok(relationship1 instanceof DS.Snapshot, 'relationship item is an instance of DS.Snapshot'); | ||
|
||
equal(relationship1.attr('id'), 1, 'relationship item id is correct'); | ||
equal(relationship1.attr('body'), 'This is the first comment', 'relationship item body is correct'); | ||
}); | ||
}); | ||
|
||
test("snapshot get() is deprecated", function() { | ||
expect(1); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World' }); | ||
var snapshot = post.snapshot(); | ||
|
||
expectDeprecation(function() { | ||
snapshot.get('title'); | ||
}, 'Using DS.Snapshot.get() is deprecated. Use .attr(), .belongsTo() or .hasMany() instead.') | ||
}); | ||
}); | ||
|
||
test("snapshot get() returns attribute", function() { | ||
expect(1); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World' }); | ||
var snapshot = post.snapshot(); | ||
|
||
equal(snapshot.get('title'), 'Hello World', 'snapshot title is correct'); | ||
}); | ||
}); | ||
|
||
test("snapshot get() returns belongsTo", function() { | ||
expect(1); | ||
|
||
run(function() { | ||
var comment = env.store.push('comment', { id: 1, body: 'This is a comment', post: 2 }); | ||
var snapshot = comment.snapshot(); | ||
var relationship = snapshot.belongsTo('post'); | ||
|
||
ok(relationship instanceof DS.Snapshot, 'relationship is an instance of DS.Snapshot'); | ||
}); | ||
}); | ||
|
||
test("snapshot get() returns hasMany", function() { | ||
expect(2); | ||
|
||
run(function() { | ||
var post = env.store.push('post', { id: 1, title: 'Hello World', comments: [2, 3] }); | ||
var snapshot = post.snapshot(); | ||
var relationship = snapshot.hasMany('comments'); | ||
|
||
ok(relationship instanceof Array, 'relationship is an instance of Array'); | ||
equal(relationship.length, 2, 'relationship has two items'); | ||
}); | ||
}); |