diff --git a/lib/relation-definition.js b/lib/relation-definition.js index 12669318..4185b22f 100644 --- a/lib/relation-definition.js +++ b/lib/relation-definition.js @@ -55,21 +55,24 @@ function normalizeType(type) { }; function extendScopeMethods(definition, scopeMethods, ext) { + var customMethods = []; var relationClass = RelationClasses[definition.type]; if (definition.type === RelationTypes.hasMany && definition.modelThrough) { relationClass = RelationClasses.hasManyThrough; } if (typeof ext === 'function') { - ext.call(definition, scopeMethods, relationClass); + customMethods = ext.call(definition, scopeMethods, relationClass); } else if (typeof ext === 'object') { for (var key in ext) { scopeMethods[key] = function () { var relation = new relationClass(definition, this); return ext[key].apply(relation, arguments); }; + if (ext[key].shared === true) scopeMethods[key].shared = true; + customMethods.push(key); } } - return scopeMethods; + return [].concat(customMethods || []); }; /** @@ -519,6 +522,16 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) { scopeMethods.build = scopeMethod(definition, 'build'); } + var customMethods = extendScopeMethods(definition, scopeMethods, params.scopeMethods); + + for (var i = 0; i < customMethods.length; i++) { + var methodName = customMethods[i]; + var method = scopeMethods[methodName]; + if (typeof method === 'function' && method.shared === true) { + modelFrom.prototype['__' + methodName + '__' + relationName] = method; + } + }; + // Mix the property and scoped methods into the prototype class defineScope(modelFrom.prototype, params.through || modelTo, relationName, function () { var filter = {}; @@ -537,7 +550,7 @@ RelationDefinition.hasMany = function hasMany(modelFrom, modelTo, params) { } return filter; - }, extendScopeMethods(definition, scopeMethods, params.scopeMethods)); + }, scopeMethods); }; @@ -1558,10 +1571,20 @@ RelationDefinition.embedsMany = function embedsMany(modelFrom, modelTo, params) scopeMethods.related = scopeMethod(definition, 'related'); // bound to definition + var customMethods = extendScopeMethods(definition, scopeMethods, params.scopeMethods); + + for (var i = 0; i < customMethods.length; i++) { + var methodName = customMethods[i]; + var method = scopeMethods[methodName]; + if (typeof method === 'function' && method.shared === true) { + modelFrom.prototype['__' + methodName + '__' + accessorName] = method; + } + }; + // Mix the property and scoped methods into the prototype class var scopeDefinition = defineScope(modelFrom.prototype, modelTo, accessorName, function () { return {}; - }, extendScopeMethods(definition, scopeMethods, params.scopeMethods)); + }, scopeMethods); scopeDefinition.related = scopeMethods.related; }; @@ -1962,10 +1985,20 @@ RelationDefinition.referencesMany = function referencesMany(modelFrom, modelTo, scopeMethods.related = scopeMethod(definition, 'related'); + var customMethods = extendScopeMethods(definition, scopeMethods, params.scopeMethods); + + for (var i = 0; i < customMethods.length; i++) { + var methodName = customMethods[i]; + var method = scopeMethods[methodName]; + if (typeof method === 'function' && method.shared === true) { + modelFrom.prototype['__' + methodName + '__' + relationName] = method; + } + }; + // Mix the property and scoped methods into the prototype class var scopeDefinition = defineScope(modelFrom.prototype, modelTo, relationName, function () { return {}; - }, extendScopeMethods(definition, scopeMethods, params.scopeMethods)); + }, scopeMethods); scopeDefinition.related = scopeMethods.related; // bound to definition }; diff --git a/test/relations.test.js b/test/relations.test.js index b6030dac..77a198f9 100644 --- a/test/relations.test.js +++ b/test/relations.test.js @@ -1851,16 +1851,23 @@ describe('relations', function () { }); it('can be declared', function (done) { + var reverse = function(cb) { + var modelInstance = this.modelInstance; + var fk = this.definition.keyFrom; + var ids = modelInstance[fk] || []; + modelInstance.updateAttribute(fk, ids.reverse(), function(err, inst) { + cb(err, inst[fk] || []); + }); + }; + + reverse.shared = true; // remoting + Category.referencesMany(Product, { scopeMethods: { - reverse: function(cb) { - var modelInstance = this.modelInstance; - var fk = this.definition.keyFrom; - var ids = modelInstance[fk] || []; - modelInstance.updateAttribute(fk, ids.reverse(), function(err, inst) { - cb(err, inst[fk] || []); - }); - } + reverse: reverse } }); + + Category.prototype['__reverse__products'].should.be.a.function; + db.automigrate(done); });