Skip to content

Commit e4dd6b1

Browse files
authored
Merge pull request #248 from digitalsadhu/fix_and_refactor_updating_of_relationships
Fix and refactor updating of relationships
2 parents a6ee62d + 06b6247 commit e4dd6b1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+672
-248
lines changed

lib/create.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
var url = require('url')
24
var utils = require('./utils')
35
var statusCodes = require('http-status-codes')

lib/delete.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
var utils = require('./utils')
24
var statusCodes = require('http-status-codes')
35

lib/deserialize.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
/* global require,module */
24
var deserializer = require('./deserializer')
35
var RelUtils = require('./utilities/relationship-utils')

lib/deserializer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
var _ = require('lodash')
24

35
function defaultBeforeDeserialize (options, cb) {

lib/errors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
var debug
24
var statusCodes = require('http-status-codes')
35

lib/headers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
'use strict'
2+
23
var is = require('type-is')
34
var _ = require('lodash')
45
var utils = require('./utils')

lib/patch.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
var statusCodes = require('http-status-codes')
24

35
module.exports = function (app, options) {

lib/querystring.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
var utils = require('./utils')
24

35
module.exports = function (app, options) {

lib/relationships.js

Lines changed: 30 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
var _ = require('lodash')
44
var utils = require('./utils')
5-
var debug = require('debug')('loopback-component-jsonapi')
5+
const linkRelatedModels = require(
6+
'./utilities/relationship-utils'
7+
).linkRelatedModels
68

79
module.exports = function (app, options) {
810
// get remote methods.
@@ -24,9 +26,7 @@ module.exports = function (app, options) {
2426
data = options.data
2527
model = utils.getModelFromContext(ctx, app)
2628

27-
relationships(id, data, model)
28-
29-
next()
29+
relationships(model, id, data).then(() => next()).catch(err => next(err))
3030
})
3131

3232
// for create
@@ -41,144 +41,42 @@ module.exports = function (app, options) {
4141
id = ctx.result.data.id
4242
data = options.data
4343
model = utils.getModelFromContext(ctx, app)
44-
relationships(id, data, model)
44+
return relationships(model, id, data)
45+
.then(() => next())
46+
.catch(err => next(err))
4547
}
4648

4749
next()
4850
})
4951
}
5052

51-
function relationships (id, data, model) {
52-
if (!data || !data.data || !id || !model || !data.data.relationships) {
53-
return
53+
function extractIdsFromResource (resource) {
54+
if (_.isArray(resource)) {
55+
return _.map(resource, 'id')
5456
}
55-
56-
_.each(data.data.relationships, function (relationship, name) {
57-
var serverRelation = model.relations[name]
58-
if (!serverRelation) return
59-
var type = serverRelation.type
60-
61-
// don't handle belongsTo in relationships function
62-
if (type === 'belongsTo') return
63-
64-
var modelTo = serverRelation.modelTo
65-
66-
var fkName = serverRelation.keyTo
67-
68-
if (type === 'belongsTo') {
69-
fkName = serverRelation.keyFrom
70-
modelTo = serverRelation.modelFrom
71-
}
72-
73-
if (!modelTo) {
74-
return false
75-
}
76-
77-
var setTo = {}
78-
setTo[fkName] = null
79-
var where = {}
80-
where[fkName] = id
81-
82-
// remove all relations to the model (eg .: post/1)
83-
if (type !== 'belongsTo') {
84-
modelTo.updateAll(where, setTo, function (err, info) {
85-
if (err) console.log(err)
86-
})
87-
}
88-
89-
var idToFind = null
90-
91-
if (_.isArray(relationship.data)) {
92-
// find all instance from the relation data eg
93-
// [{type: "comments", id: 1}, {type: "comments", id: 2}]
94-
_.each(relationship.data, function (item) {
95-
idToFind = item.id
96-
97-
if (type === 'belongsTo') {
98-
where[fkName] = item.id
99-
idToFind = id
100-
}
101-
102-
updateRelation(modelTo, idToFind, where)
103-
})
104-
105-
if (serverRelation.modelThrough) {
106-
var modelThrough = serverRelation.modelThrough
107-
var key = keyByModel(modelThrough, modelTo)
108-
var data = {}
109-
data[fkName] = id
110-
var stringIds = false
111-
112-
var payloadIds = _.map(relationship.data, function (item) {
113-
if (typeof item.id === 'string') {
114-
stringIds = true
115-
}
116-
return item.id
117-
})
118-
119-
modelThrough.find({ where: data, fields: key }, function (
120-
err,
121-
instances
122-
) {
123-
if (err) return
124-
var serverIds = _.map(instances, function (instance) {
125-
return stringIds ? instance[key].toString() : instance[key]
126-
})
127-
// to delete
128-
var toDelete = _.difference(serverIds, payloadIds)
129-
_.each(toDelete, function (id) {
130-
data[key] = id
131-
modelThrough.destroyAll(data)
132-
})
133-
// new
134-
var newAssocs = _.difference(payloadIds, serverIds)
135-
_.each(newAssocs, function (id) {
136-
data[key] = id
137-
modelThrough.create(data)
138-
})
139-
})
140-
}
141-
} else {
142-
if (relationship.data === null) {
143-
where[fkName] = null
144-
updateRelation(model, id, where)
145-
return
146-
}
147-
148-
idToFind = relationship.data.id
149-
150-
if (type === 'belongsTo') {
151-
idToFind = id
152-
where[fkName] = relationship.data.id
153-
}
154-
// relationship: {data: {type: "comments": id: 1}}
155-
updateRelation(modelTo, idToFind, where)
156-
}
157-
})
57+
return _.get(resource, 'id', null)
15858
}
15959

160-
// if the instance exist, then update it (create relationship),
161-
// according to JSON API spec we MUST NOT create new ones
162-
function updateRelation (model, id, data) {
163-
model.findById(id, function (err, instance) {
164-
if (err) console.log(err)
60+
function relationships (model, id, payload) {
61+
if (!id || !model) return
62+
const relationships = _.get(payload, 'data.relationships', {})
16563

166-
if (instance) {
167-
instance.updateAttributes(data)
168-
}
169-
})
170-
}
64+
return Promise.all(
65+
Object.keys(relationships).map(relationName => {
66+
const relationship = relationships[relationName]
67+
const relationDefn = model.relations[relationName]
68+
if (!relationDefn) return
17169

172-
function keyByModel (assocModel, model) {
173-
var key = null
174-
_.each(assocModel.relations, function (relation) {
175-
if (relation.modelTo.modelName === model.modelName) {
176-
key = relation.keyFrom
177-
}
178-
})
70+
const type = relationDefn.type
71+
const modelTo = relationDefn.modelTo
17972

180-
if (key === null) {
181-
debug('Can not find relation for ' + model.modelName)
182-
}
183-
return key
73+
// don't handle belongsTo in relationships function
74+
if (!modelTo || type === 'belongsTo') return
75+
76+
const data = extractIdsFromResource(relationship.data)
77+
const from = { model, id }
78+
const to = { model: modelTo, data }
79+
return linkRelatedModels(relationName, from, to)
80+
})
81+
)
18482
}

lib/removeRemoteMethods.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict'
2+
13
module.exports = function (app, options) {
24
var models = app.models
35

0 commit comments

Comments
 (0)