Skip to content
This repository has been archived by the owner on Aug 5, 2021. It is now read-only.

Commit

Permalink
relations with scope and args
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilWaldmann committed Jul 28, 2017
1 parent 919a385 commit 1f49a18
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 8 deletions.
56 changes: 49 additions & 7 deletions lib/persistence/include.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ exports.model = {
name_tree: relations[i].name_tree,
sub_includes: relations[i].sub_relations,
as: relations[i].as,
scope: relations[i].scope
scope: relations[i].scope,
args: relations[i].args
})
}

Expand Down Expand Up @@ -186,7 +187,7 @@ exports.definition = {
self.callInterceptors('onInclude', [Chain, records, include, cache, data], function(okay){
if(okay){
Chain.exec(function(result){
self.callInterceptors('afterInclude', [Chain.definition.model, result, records, include, cache, data], function(){
self.callInterceptors('afterInclude', [Chain.definition.model, result, records, include, cache, data, Chain], function(){
includeDone()
})
}).catch(function(err){
Expand Down Expand Up @@ -239,6 +240,7 @@ exports.definition = {


var relation = include.relation
var chain

if(relation.polymorph && relation.type_key){
var models = []
Expand All @@ -255,12 +257,31 @@ exports.definition = {

var Model = this.definition.store.Model(modelName)
if(Model){
Chains.push(Model.chain())
chain = Model.chain()
if(relation.scope && chain[relation.scope]) chain[relation.scope].apply(chain, include.args || [])
Chains.push(chain)
}
}
}
}else{
Chains.push(relation.model.chain())
chain = relation.model.chain()

if(relation.scope && chain[relation.scope]){
chain[relation.scope].apply(chain, include.args || [])
}
}

if(chain){
if(relation.scope_per_record){
// expensive!!
for(var i = 0; i < records.length; i++){
var clone = chain.clone()
clone.setInternal('recordIndex', i)
Chains.push(clone)
}
}else{
Chains.push(chain)
}
}
}, 100)

Expand All @@ -285,7 +306,15 @@ exports.definition = {
if(conditions.hasOwnProperty(base) && conditions[base] && conditions[base].attribute){
condition[base] = []

for(var i = 0; i < records.length; i++){
var i = 0
var length = records.length

if(relation.scope_per_record){
i = Chain.getInternal('recordIndex')
length = i + 1
}

for(i; i < length; i++){
if(relation.polymorph){
var modelName = records[i][relation.type_key]

Expand Down Expand Up @@ -317,15 +346,28 @@ exports.definition = {



this.afterInclude(function(Model, result, records, include, cache){
this.afterInclude(function(Model, result, records, include, cache, data, Chain){
if(!include.relation) return // scopes do not have any relations - filter them out.

if(!result || result.length === 0) return 'STOP'
if(result === null || result === undefined || result.length === 0) return 'STOP'
if(!Array.isArray(result)) result = [result]

var relation = include.relation
var conditions = relation.conditions


if(relation.scope_per_record){
var index = Chain.getInternal('recordIndex')

if(relation.type === 'has_many' || relation.type === 'belongs_to_many'){
records[index][relation.name] = result
}else{
records[index][relation.name] = result[0]
}

return
}

if(Object.keys(conditions).length === 0) return

// add result into records - based in the conditions - a kind of offline join
Expand Down
8 changes: 8 additions & 0 deletions lib/persistence/relations.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ exports.definition = {
var primaryKey = this.primary_keys[0] || 'id' // TODO: support multiple primary keys...
options.conditions = options.conditions || {}

if(options.scope){
if(options.scope.match(/^!/)){
// scope_per_record is expensive! It will run a query for every base record to receive relational data
options.scope = options.scope.replace(/^!/, '')
options.scope_per_record = false
}
options.scope_per_record = true
}

if(options.as){
options.foreign_key = options.foreign_key || options.as + '_' + primaryKey
Expand Down
23 changes: 22 additions & 1 deletion lib/persistence/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,28 @@ exports.utils = {
relName = tmpSplit[0]
scope = tmpSplit[1]

var args = []

relation = parent.definition.relations[relName]
if(relation){
if(relations[i][name].$args){
args = relations[i][name].$args
delete relations[i][name].$args

if(!Array.isArray(args) && typeof args === 'object'){
if(relation.scope && relation.model[relation.scope] && relation.model[relation.scope].options){
var argsMapping = relation.model[relation.scope].options.args_mapping

if(argsMapping){
args = argsMapping.map(function(name){
return args[name]
})
}
}
}
}


if(relation.through){
throughRel = {}
throughRel[relation.through] = {}
Expand All @@ -85,7 +105,8 @@ exports.utils = {
name_tree: nameTree.concat(relation.name),
sub: relations[i][name],
sub_relations: subRelations,
scope: scope
scope: scope,
args: args
})

if(through){
Expand Down
18 changes: 18 additions & 0 deletions test/sql/__shared/includes-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module.exports = function(title, beforeFn, afterFn, storeConf){
this.hasOne('avatar')
this.hasMany('unread_posts')
this.hasMany('unread', {through: 'unread_posts'})
this.hasOne('last_post', {model: 'Post', scope: '!recent'})
this.hasMany('unread_threads', {through: 'unread', relation: 'thread'})
this.hasMany('poly_things')
this.hasMany('members', {through: 'poly_things', relation: 'member'})
Expand All @@ -44,6 +45,10 @@ module.exports = function(title, beforeFn, afterFn, storeConf){
this.belongsTo('user')
this.belongsTo('thread')
this.belongsTo('thread_autor', {through: 'thread', relation: 'user'})

this.scope('recent', function(){
this.order('id', true).limit(1)
})
})
store.Model('Thread', function(){
this.belongsTo('user')
Expand Down Expand Up @@ -596,6 +601,19 @@ module.exports = function(title, beforeFn, afterFn, storeConf){
})
})
})


it('include a relation with scope', function(next){
store.ready(function(){
var User = store.Model('User')
User.include('last_post').exec(function(result){
result.length.should.be.equal(3)
result[0].last_post.id.should.be.equal(3)
result[1].last_post.id.should.be.equal(4)
next()
})
})
})
})
})
}

0 comments on commit 1f49a18

Please sign in to comment.