Skip to content

Commit

Permalink
Stable Version 1.0.0-alpha.5-5.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdobry committed Dec 1, 2014
1 parent 69c4903 commit 1e0f08f
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 75 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,11 @@
##### 1.0.0-alpha.5-5 - 30 November 2014

###### Breaking API changes
- findInverseLinks, findBelongsTo, findHasOne, and findHasMany now default to true

###### Backwards compatible bug fixes
- Backport jmdobry/angular-data#253

##### 1.0.0-alpha.5-3 - 28 November 2014

###### Backwards compatible API changes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -10,7 +10,7 @@ Unlike Backbone and Ember Models, js-data does not require the use of getters an

Supporting relations, computed properties, model lifecycle control and a slew of other features, js-data is the tool for giving your data the respect it deserves.

__Latest Release:__ [1.0.0-alpha.5-4](https://github.com/js-data/js-data/releases/tag/1.0.0-alpha.5-4)
__Latest Release:__ [1.0.0-alpha.5-5](https://github.com/js-data/js-data/releases/tag/1.0.0-alpha.5-5)

js-data is pre-release. The API is subject to change, though the current api is well tested.

Expand Down
2 changes: 1 addition & 1 deletion bower.json
@@ -1,7 +1,7 @@
{
"name": "js-data",
"description": "Robust, framework-agnostic in-memory data store.",
"version": "1.0.0-alpha.5-4",
"version": "1.0.0-alpha.5-5",
"homepage": "http://www.js-data.io",
"repository": {
"type": "git",
Expand Down
72 changes: 44 additions & 28 deletions dist/js-data.js
@@ -1,7 +1,7 @@
/**
* @author Jason Dobry <jason.dobry@gmail.com>
* @file js-data.js
* @version 1.0.0-alpha.5-4 - Homepage <http://www.js-data.io/>
* @version 1.0.0-alpha.5-5 - Homepage <http://www.js-data.io/>
* @copyright (c) 2014 Jason Dobry
* @license MIT <https://github.com/js-data/js-data/blob/master/LICENSE>
*
Expand Down Expand Up @@ -3495,10 +3495,10 @@ defaultsPrototype.upsert = !!DSUtils.w;
defaultsPrototype.cacheResponse = !!DSUtils.w;
defaultsPrototype.bypassCache = false;
defaultsPrototype.ignoreMissing = false;
defaultsPrototype.findInverseLinks = false;
defaultsPrototype.findBelongsTo = false;
defaultsPrototype.findHasOn = false;
defaultsPrototype.findHasMany = false;
defaultsPrototype.findInverseLinks = true;
defaultsPrototype.findBelongsTo = true;
defaultsPrototype.findHasOne = true;
defaultsPrototype.findHasMany = true;
defaultsPrototype.reapInterval = !!DSUtils.w ? 30000 : false;
defaultsPrototype.reapAction = !!DSUtils.w ? 'inject' : 'none';
defaultsPrototype.maxAge = false;
Expand Down Expand Up @@ -4443,25 +4443,6 @@ module.exports = {
var DSUtils = require('../../utils');
var DSErrors = require('../../errors');

function _injectRelations(definition, injected, options) {
var _this = this;

DSUtils.forEach(definition.relationList, function (def) {
var relationName = def.relation;
var relationDef = _this.definitions[relationName];
if (injected[def.localField]) {
if (!relationDef) {
throw new DSErrors.R(definition.name + ' relation is defined, but the resource is not!');
}
try {
injected[def.localField] = _this.inject(relationName, injected[def.localField], options);
} catch (err) {
console.error(definition.name + ': Failed to inject ' + def.type + ' relation: "' + relationName + '"!', err);
}
}
});
}

function _getReactFunction(DS, definition, resource) {
var name = definition.name;
return function _react(added, removed, changed, oldValueFn, firstTime) {
Expand Down Expand Up @@ -4553,6 +4534,45 @@ function _inject(definition, resource, attrs, options) {
throw error;
} else {
try {
DSUtils.forEach(definition.relationList, function (def) {
var relationName = def.relation;
var relationDef = _this.definitions[relationName];
var toInject = attrs[def.localField];
if (toInject) {
if (!relationDef) {
throw new DSErrors.R(definition.name + ' relation is defined but the resource is not!');
}
if (DSUtils.isArray(toInject)) {
var items = [];
DSUtils.forEach(toInject, function (toInjectItem) {
if (toInjectItem !== _this.store[relationName][toInjectItem[relationDef.idAttribute]]) {
try {
var injectedItem = _this.inject(relationName, toInjectItem, options);
if (def.foreignKey) {
injectedItem[def.foreignKey] = attrs[definition.idAttribute];
}
items.push(injectedItem);
} catch (err) {
console.error(definition.name + ': Failed to inject ' + def.type + ' relation: "' + relationName + '"!', err);
}
}
});
attrs[def.localField] = items;
} else {
if (toInject !== _this.store[relationName][toInject[relationDef.idAttribute]]) {
try {
attrs[def.localField] = _this.inject(relationName, attrs[def.localField], options);
if (def.foreignKey) {
attrs[def.localField][def.foreignKey] = attrs[definition.idAttribute];
}
} catch (err) {
console.error(definition.name + ': Failed to inject ' + def.type + ' relation: "' + relationName + '"!', err);
}
}
}
}
});

var id = attrs[idA];
var item = _this.get(definition.name, id);
var initialLastModified = item ? resource.modified[id] : 0;
Expand Down Expand Up @@ -4582,10 +4602,6 @@ function _inject(definition, resource, attrs, options) {

resource.index[id] = item;
_react.call(item, {}, {}, {}, null, true);

if (definition.relations) {
_injectRelations.call(_this, definition, item, options);
}
} else {
DSUtils.deepMixIn(item, attrs);
if (definition.resetHistoryOnInject) {
Expand Down
4 changes: 2 additions & 2 deletions dist/js-data.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "js-data",
"description": "Robust, framework-agnostic in-memory data store.",
"version": "1.0.0-alpha.5-4",
"version": "1.0.0-alpha.5-5",
"homepage": "http://www.js-data.io",
"repository": {
"type": "git",
Expand Down
8 changes: 4 additions & 4 deletions src/datastore/index.js
Expand Up @@ -71,10 +71,10 @@ defaultsPrototype.upsert = !!DSUtils.w;
defaultsPrototype.cacheResponse = !!DSUtils.w;
defaultsPrototype.bypassCache = false;
defaultsPrototype.ignoreMissing = false;
defaultsPrototype.findInverseLinks = false;
defaultsPrototype.findBelongsTo = false;
defaultsPrototype.findHasOn = false;
defaultsPrototype.findHasMany = false;
defaultsPrototype.findInverseLinks = true;
defaultsPrototype.findBelongsTo = true;
defaultsPrototype.findHasOne = true;
defaultsPrototype.findHasMany = true;
defaultsPrototype.reapInterval = !!DSUtils.w ? 30000 : false;
defaultsPrototype.reapAction = !!DSUtils.w ? 'inject' : 'none';
defaultsPrototype.maxAge = false;
Expand Down
62 changes: 39 additions & 23 deletions src/datastore/sync_methods/inject.js
@@ -1,25 +1,6 @@
var DSUtils = require('../../utils');
var DSErrors = require('../../errors');

function _injectRelations(definition, injected, options) {
var _this = this;

DSUtils.forEach(definition.relationList, function (def) {
var relationName = def.relation;
var relationDef = _this.definitions[relationName];
if (injected[def.localField]) {
if (!relationDef) {
throw new DSErrors.R(definition.name + ' relation is defined, but the resource is not!');
}
try {
injected[def.localField] = _this.inject(relationName, injected[def.localField], options);
} catch (err) {
console.error(definition.name + ': Failed to inject ' + def.type + ' relation: "' + relationName + '"!', err);
}
}
});
}

function _getReactFunction(DS, definition, resource) {
var name = definition.name;
return function _react(added, removed, changed, oldValueFn, firstTime) {
Expand Down Expand Up @@ -111,6 +92,45 @@ function _inject(definition, resource, attrs, options) {
throw error;
} else {
try {
DSUtils.forEach(definition.relationList, function (def) {
var relationName = def.relation;
var relationDef = _this.definitions[relationName];
var toInject = attrs[def.localField];
if (toInject) {
if (!relationDef) {
throw new DSErrors.R(definition.name + ' relation is defined but the resource is not!');
}
if (DSUtils.isArray(toInject)) {
var items = [];
DSUtils.forEach(toInject, function (toInjectItem) {
if (toInjectItem !== _this.store[relationName][toInjectItem[relationDef.idAttribute]]) {
try {
var injectedItem = _this.inject(relationName, toInjectItem, options);
if (def.foreignKey) {
injectedItem[def.foreignKey] = attrs[definition.idAttribute];
}
items.push(injectedItem);
} catch (err) {
console.error(definition.name + ': Failed to inject ' + def.type + ' relation: "' + relationName + '"!', err);
}
}
});
attrs[def.localField] = items;
} else {
if (toInject !== _this.store[relationName][toInject[relationDef.idAttribute]]) {
try {
attrs[def.localField] = _this.inject(relationName, attrs[def.localField], options);
if (def.foreignKey) {
attrs[def.localField][def.foreignKey] = attrs[definition.idAttribute];
}
} catch (err) {
console.error(definition.name + ': Failed to inject ' + def.type + ' relation: "' + relationName + '"!', err);
}
}
}
}
});

var id = attrs[idA];
var item = _this.get(definition.name, id);
var initialLastModified = item ? resource.modified[id] : 0;
Expand Down Expand Up @@ -140,10 +160,6 @@ function _inject(definition, resource, attrs, options) {

resource.index[id] = item;
_react.call(item, {}, {}, {}, null, true);

if (definition.relations) {
_injectRelations.call(_this, definition, item, options);
}
} else {
DSUtils.deepMixIn(item, attrs);
if (definition.resetHistoryOnInject) {
Expand Down
83 changes: 69 additions & 14 deletions test/both/datastore/sync_methods/inject.test.js
Expand Up @@ -64,8 +64,8 @@ describe('DS#inject', function () {
store.inject('comment', comment3);
store.inject('profile', profile4);

assert.deepEqual(JSON.stringify(store.get('user', 1)), JSON.stringify(user1));
assert.deepEqual(JSON.stringify(store.get('organization', 2)), JSON.stringify(organization2));
assert.deepEqual(store.get('user', 1).id, user1.id);
assert.deepEqual(store.get('organization', 2).id, organization2.id);
assert.deepEqual(store.get('comment', 3).id, comment3.id);
assert.deepEqual(store.get('profile', 4).id, profile4.id);

Expand All @@ -89,23 +89,23 @@ describe('DS#inject', function () {
assert.deepEqual(store.get('profile', 21).content, profile21.content);

// user10 relations
assert.deepEqual(JSON.stringify(store.get('comment', 11)), JSON.stringify(store.get('user', 10).comments[0]));
assert.deepEqual(JSON.stringify(store.get('comment', 12)), JSON.stringify(store.get('user', 10).comments[1]));
assert.deepEqual(JSON.stringify(store.get('comment', 13)), JSON.stringify(store.get('user', 10).comments[2]));
assert.deepEqual(JSON.stringify(store.get('organization', 14)), JSON.stringify(store.get('user', 10).organization));
assert.deepEqual(JSON.stringify(store.get('profile', 15)), JSON.stringify(store.get('user', 10).profile));
assert.deepEqual(store.get('comment', 11), store.get('user', 10).comments[0]);
assert.deepEqual(store.get('comment', 12), store.get('user', 10).comments[1]);
assert.deepEqual(store.get('comment', 13), store.get('user', 10).comments[2]);
assert.deepEqual(store.get('organization', 14), store.get('user', 10).organization);
assert.deepEqual(store.get('profile', 15), store.get('user', 10).profile);

// organization15 relations
assert.deepEqual(JSON.stringify(store.get('user', 16)), JSON.stringify(store.get('organization', 15).users[0]));
assert.deepEqual(JSON.stringify(store.get('user', 17)), JSON.stringify(store.get('organization', 15).users[1]));
assert.deepEqual(JSON.stringify(store.get('user', 18)), JSON.stringify(store.get('organization', 15).users[2]));
assert.deepEqual(store.get('user', 16), store.get('organization', 15).users[0]);
assert.deepEqual(store.get('user', 17), store.get('organization', 15).users[1]);
assert.deepEqual(store.get('user', 18), store.get('organization', 15).users[2]);

// comment19 relations
assert.deepEqual(JSON.stringify(store.get('user', 20)), JSON.stringify(store.get('comment', 19).user));
assert.deepEqual(JSON.stringify(store.get('user', 19)), JSON.stringify(store.get('comment', 19).approvedByUser));
assert.deepEqual(store.get('user', 20), store.get('comment', 19).user);
assert.deepEqual(store.get('user', 19), store.get('comment', 19).approvedByUser);

// profile21 relations
assert.deepEqual(JSON.stringify(store.get('user', 22)), JSON.stringify(store.get('profile', 21).user));
assert.deepEqual(store.get('user', 22), store.get('profile', 21).user);
});
it('should find inverse links', function () {
store.inject('user', { organizationId: 5, id: 1 });
Expand All @@ -114,7 +114,7 @@ describe('DS#inject', function () {

assert.isObject(store.get('user', 1).organization);

assert.isUndefined(store.get('user', 1).comments);
assert.deepEqual(store.get('user', 1).comments, []);

store.inject('comment', { approvedBy: 1, id: 23 }, { findInverseLinks: true });

Expand Down Expand Up @@ -186,4 +186,59 @@ describe('DS#inject', function () {
assert.isDefined(store.get('foo', 6));
assert.isDefined(store.get('foo', 7));
});
it('should work when injecting child relations multiple times', function () {
var Parent = store.defineResource({
name: 'parent',
relations: {
hasMany: {
child: {
localField: 'children',
foreignKey: 'parentId'
}
}
}
});

var Child = store.defineResource({
name: 'child',
relations: {
belongsTo: {
parent: {
localField: 'parent',
localKey: 'parentId'
}
}
}
});

Parent.inject({
id: 1,
name: 'parent1',
children: [{
id: 1,
name: 'child1'
}]
});

assert.isTrue(Parent.get(1).children[0] instanceof Child.Child);

Parent.inject({
id: 1,
name: 'parent',
children: [
{
id: 1,
name: 'Child-1'
},
{
id: 2,
name: 'Child-2'
}
]
});

assert.isTrue(Parent.get(1).children[0] instanceof Child.Child);
assert.isTrue(Parent.get(1).children[1] instanceof Child.Child);
assert.deepEqual(Child.filter({ parentId: 1 }), Parent.get(1).children);
});
});
4 changes: 3 additions & 1 deletion test/browser/datastore/async_methods/create.test.js
Expand Up @@ -112,7 +112,8 @@ describe('DS#create', function () {
email: 'sally@test.com'
}
}, {
findBelongsTo: true
findBelongsTo: true,
findInverseLinks: true
}).then(function (user) {
assert.equal(user.id, payload.id, 'user should have been created');

Expand All @@ -125,6 +126,7 @@ describe('DS#create', function () {
assert.equal(store.get('user', 99).id, payload.id);
assert.isObject(store.get('user', 99).profile);
assert.equal(store.get('profile', 999).id, 999);
console.log(store.get('profile', 999).user);
assert.isObject(store.get('profile', 999).user);

store.find('user', 99); // should not trigger another http request
Expand Down

0 comments on commit 1e0f08f

Please sign in to comment.