Skip to content

Commit 4feba03

Browse files
committed
Merge pull request #59 from BenjaminHorn/master
relation's related link
2 parents a4fee09 + f8be8c9 commit 4feba03

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

lib/serializer.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var inflection = require('inflection');
33
var utils = require('./utils');
44

55
module.exports = function serializer (type, data, relations, options) {
6+
67
var result = null;
78
var resultData = {};
89

@@ -110,16 +111,33 @@ function parseCollection (type, data, relations, options) {
110111
*/
111112
function parseRelations (data, relations, options) {
112113
var relationships = {};
114+
115+
var topLevel = options.topLevelLinks.self;
116+
var parts = topLevel.split('/');
117+
var collection = parts[parts.length - 1];
118+
113119
_.each(relations, function (relation, name) {
120+
114121
var pkName = relation.keyFrom;
115122
var fkName = relation.keyTo;
116123

117-
//If relation is belongsTo then pk and fk are the other way around
124+
// If relation is belongsTo then pk and fk are the other way around
118125
if (relation.type === 'belongsTo' || relation.type === 'referencesMany') {
119126
pkName = relation.keyTo;
120127
fkName = relation.keyFrom;
121128
}
122129

130+
// Items of /:collection and /:collection/:id/:relatedcollection
131+
// should have the same relationship object.
132+
// Without this /:collection/:id/:relatedcollection relationship
133+
// object is the same as /:collection/:id's.
134+
if (collection === name) {
135+
// fk should not be leaked out of the server
136+
delete data[fkName];
137+
relationships = parseRelations(data, relation.modelTo.relations, options);
138+
return false;
139+
}
140+
123141
var pk = data[pkName];
124142
var fk = data[fkName];
125143

@@ -130,6 +148,7 @@ function parseRelations (data, relations, options) {
130148
// Relationship `links` should always be defined unless this is a
131149
// relationship request
132150
if (!options.isRelationshipRequest) {
151+
133152
relationships[name] = {
134153
links: {
135154
related: options.host + options.restApiRoot + '/' + fromType + '/' + pk + '/' + name
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
var request = require('supertest');
2+
var loopback = require('loopback');
3+
var expect = require('chai').expect;
4+
var JSONAPIComponent = require('../');
5+
var app, Rule, Action, Card, ds;
6+
7+
describe('belongsTo through hasMany', function () {
8+
beforeEach(function () {
9+
app = loopback();
10+
app.set('legacyExplorer', false);
11+
ds = loopback.createDataSource('memory');
12+
13+
Rule = ds.createModel('rule', {
14+
id: {type: Number, id: true},
15+
name: String
16+
});
17+
18+
app.model(Rule);
19+
20+
Action = ds.createModel('action', {
21+
id: {type: Number, id: true},
22+
cardId: Number,
23+
name: String
24+
});
25+
26+
app.model(Action);
27+
28+
Card = ds.createModel('card', {
29+
id: {type: Number, id: true},
30+
title: String
31+
});
32+
33+
app.model(Card);
34+
35+
Rule.hasMany(Action, {as: 'actions', foreignKey: 'ruleId'});
36+
Action.belongsTo(Card, {as: 'card', foreignKey: 'cardId'});
37+
Card.hasMany(Action, {as: 'actions', foreignKey: 'cardId'});
38+
app.use(loopback.rest());
39+
JSONAPIComponent(app, {restApiRoot: '/'});
40+
});
41+
42+
describe('relationship should point to its relationship', function () {
43+
44+
beforeEach(function (done) {
45+
Rule.create({
46+
name: 'Rule 1'
47+
}, function (err, rule) {
48+
expect(err).to.equal(null);
49+
rule.actions.create([
50+
{name: 'Action 1', cardId: 1},
51+
{name: 'Action 2', cardId: 1}
52+
], function (err, res) {
53+
expect(err).to.equal(null);
54+
Card.create([{title: 'Card 1'}], done);
55+
});
56+
});
57+
});
58+
59+
it('GET /rules/1/actions', function (done) {
60+
request(app).get('/rules/1/actions')
61+
.end(function (err, res) {
62+
expect(err).to.equal(null);
63+
expect(res.body.data[0].relationships.card).to.be.an('object');
64+
expect(res.body.data[0].relationships.card.links).to.be.an('object');
65+
expect(res.body.data[0].relationships.card.links.related).to.match(/\/actions\/1\/card/);
66+
expect(res.body.data[1].relationships.card.links.related).to.match(/\/actions\/2\/card/);
67+
done();
68+
});
69+
});
70+
71+
});
72+
73+
});

0 commit comments

Comments
 (0)