Skip to content

Commit 6752dd3

Browse files
authored
Merge pull request #2703 from strongloop/fix_remoting
Fix remote method inheritance
2 parents 3eb9009 + d4b8cf6 commit 6752dd3

File tree

2 files changed

+142
-1
lines changed

2 files changed

+142
-1
lines changed

lib/registry.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Registry.prototype.createModel = function(name, properties, options) {
121121
var model = BaseModel.extend(name, properties, options);
122122
model.registry = this;
123123

124-
this._defineRemoteMethods(model, options.methods);
124+
this._defineRemoteMethods(model, model.settings.methods);
125125

126126
return model;
127127
};
@@ -244,6 +244,15 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
244244
modelName);
245245
}
246246

247+
var newMethodNames = config.methods && Object.keys(config.methods);
248+
var hasNewMethods = newMethodNames && newMethodNames.length;
249+
var hasDescendants = this.getModelByType(ModelCtor) !== ModelCtor;
250+
if (hasNewMethods && hasDescendants) {
251+
g.warn(
252+
'Child models of `%s` will not inherit newly defined remote methods %s.',
253+
modelName, newMethodNames);
254+
}
255+
247256
// Remote methods
248257
this._defineRemoteMethods(ModelCtor, config.methods);
249258
};

test/loopback.test.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ var it = require('./util/it');
77
var describe = require('./util/describe');
88
var Domain = require('domain');
99
var EventEmitter = require('events').EventEmitter;
10+
var loopback = require('../');
11+
var expect = require('chai').expect;
12+
var assert = require('assert');
1013

1114
describe('loopback', function() {
1215
var nameCounter = 0;
@@ -608,4 +611,133 @@ describe('loopback', function() {
608611
expect(methodNames).to.include('prototype.instanceMethod');
609612
});
610613
});
614+
615+
describe('Remote method inheritance', function() {
616+
var app;
617+
618+
beforeEach(setupLoopback);
619+
620+
it('inherits remote methods defined via createModel', function() {
621+
var Base = app.registry.createModel('Base', {}, {
622+
methods: {
623+
greet: {
624+
http: { path: '/greet' },
625+
},
626+
},
627+
});
628+
629+
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
630+
base: 'Base',
631+
methods: {
632+
hello: {
633+
http: { path: '/hello' },
634+
},
635+
},
636+
});
637+
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
638+
639+
expect(methodNames).to.include('greet');
640+
expect(methodNames).to.include('hello');
641+
});
642+
643+
it('same remote method with different metadata should override parent', function() {
644+
var Base = app.registry.createModel('Base', {}, {
645+
methods: {
646+
greet: {
647+
http: { path: '/greet' },
648+
},
649+
},
650+
});
651+
652+
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
653+
base: 'Base',
654+
methods: {
655+
greet: {
656+
http: { path: '/hello' },
657+
},
658+
},
659+
});
660+
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
661+
var baseMethod = Base.sharedClass.findMethodByName('greet');
662+
var customMethod = MyCustomModel.sharedClass.findMethodByName('greet');
663+
664+
// Base Method
665+
expect(baseMethod.http).to.eql({ path: '/greet' });
666+
expect(baseMethod.http.path).to.equal('/greet');
667+
expect(baseMethod.http.path).to.not.equal('/hello');
668+
669+
// Custom Method
670+
expect(methodNames).to.include('greet');
671+
expect(customMethod.http).to.eql({ path: '/hello' });
672+
expect(customMethod.http.path).to.equal('/hello');
673+
expect(customMethod.http.path).to.not.equal('/greet');
674+
});
675+
676+
it('does not inherit remote methods defined via configureModel', function() {
677+
var Base = app.registry.createModel('Base');
678+
app.registry.configureModel(Base, {
679+
dataSource: null,
680+
methods: {
681+
greet: {
682+
http: { path: '/greet' },
683+
},
684+
},
685+
});
686+
687+
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
688+
base: 'Base',
689+
methods: {
690+
hello: {
691+
http: { path: '/hello' },
692+
},
693+
},
694+
});
695+
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
696+
697+
expect(methodNames).to.not.include('greet');
698+
expect(methodNames).to.include('hello');
699+
});
700+
701+
it('does not inherit remote methods defined via configureModel after child model ' +
702+
'was created', function() {
703+
var Base = app.registry.createModel('Base');
704+
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
705+
base: 'Base',
706+
});
707+
708+
app.registry.configureModel(Base, {
709+
dataSource: null,
710+
methods: {
711+
greet: {
712+
http: { path: '/greet' },
713+
},
714+
},
715+
});
716+
717+
app.registry.configureModel(MyCustomModel, {
718+
dataSource: null,
719+
methods: {
720+
hello: {
721+
http: { path: '/hello' },
722+
},
723+
},
724+
});
725+
var baseMethodNames = getAllMethodNamesWithoutClassName(Base);
726+
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
727+
728+
expect(baseMethodNames).to.include('greet');
729+
expect(methodNames).to.not.include('greet');
730+
expect(methodNames).to.include('hello');
731+
});
732+
733+
function setupLoopback() {
734+
app = loopback({ localRegistry: true });
735+
}
736+
737+
function getAllMethodNamesWithoutClassName(Model) {
738+
return Model.sharedClass.methods().map(function(m) {
739+
return m.stringName.replace(/^[^.]+\./, ''); // drop the class name
740+
});
741+
}
742+
});
611743
});

0 commit comments

Comments
 (0)