Skip to content

Commit 982b8ac

Browse files
committed
Merge pull request #2174 from strongloop/change_remote_method
Remove constraint making isStatic required
2 parents b4e2303 + b5b900e commit 982b8ac

File tree

4 files changed

+135
-7
lines changed

4 files changed

+135
-7
lines changed

3.0-RELEASE-NOTES.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,34 @@ via `global.Promise`,
3232
you will have to check all places where you are using non-standard promise API
3333
and update them to use Bluebird API instead.
3434

35-
Please see [Related code change](https://github.com/strongloop/loopback/pull/1896) here.
35+
Please see [Related code change](https://github.com/strongloop/loopback/pull/1896) here.
36+
37+
## new method of defining remoting metadata
38+
39+
In 2.0, remote methods were defined as:
40+
```
41+
methods: {
42+
staticMethod: {
43+
isStatic: true,
44+
http: { path: '/static' }
45+
},
46+
instanceMethod: {
47+
isStatic: false,
48+
http: { path: '/instance' }
49+
}
50+
}
51+
```
52+
53+
For 3.0, the isStatic flag is no longer required and will be determined from the method name.
54+
Method name starting with "prototype." will be the same as having isStatic flag set to false.
55+
```
56+
methods: {
57+
staticMethod: {
58+
http: { path: '/static' }
59+
},
60+
'prototype.instanceMethod': {
61+
http: { path: '/instance' }
62+
}
63+
```
64+
65+
Please see [related code change](https://github.com/strongloop/loopback/pull/2174) here.

lib/model.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,9 @@ module.exports = function(registry) {
415415

416416
Model.remoteMethod = function(name, options) {
417417
if (options.isStatic === undefined) {
418-
options.isStatic = true;
418+
var m = name.match(/^prototype\.(.*)$/);
419+
options.isStatic = !m;
420+
name = options.isStatic ? name : m[1];
419421
}
420422
this.sharedClass.defineMethod(name, options);
421423
};

lib/registry.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var juggler = require('loopback-datasource-juggler');
44
var debug = require('debug')('loopback:registry');
55
var DataSource = juggler.DataSource;
66
var ModelBuilder = juggler.ModelBuilder;
7+
var deprecated = require('depd')('strong-remoting');
78

89
module.exports = Registry;
910

@@ -258,12 +259,19 @@ Registry.prototype._defineRemoteMethods = function(ModelCtor, methods) {
258259

259260
Object.keys(methods).forEach(function(key) {
260261
var meta = methods[key];
262+
var m = key.match(/^prototype\.(.*)$/);
263+
var isStatic = !m;
264+
261265
if (typeof meta.isStatic !== 'boolean') {
262-
console.warn('Remoting metadata for "%s.%s" is missing "isStatic" ' +
263-
'flag, the method is registered as an instance method.',
264-
ModelCtor.modelName,
265-
key);
266-
console.warn('This behaviour may change in the next major version.');
266+
key = isStatic ? key : m[1];
267+
meta.isStatic = isStatic;
268+
} else if (meta.isStatic && m) {
269+
throw new Error('Remoting metadata for ' + ModelCtor.modelName + '.' +
270+
key + ' "isStatic" does not match new method name-based style.');
271+
} else {
272+
key = isStatic ? key : m[1];
273+
deprecated('Remoting metadata "isStatic" is deprecated. Please ' +
274+
'specify "prototype.name" in method name instead for isStatic=false.');
267275
}
268276
ModelCtor.remoteMethod(key, meta);
269277
});

test/loopback.test.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,4 +631,92 @@ describe('loopback', function() {
631631
});
632632
});
633633
});
634+
635+
describe('new remote method configuration', function() {
636+
function getAllMethodNamesWithoutClassName(TestModel) {
637+
return TestModel.sharedClass.methods().map(function(m) {
638+
return m.stringName.replace(/^[^.]+\./, ''); // drop the class name
639+
});
640+
}
641+
642+
it('treats method names that don\'t start with "prototype." as "isStatic:true"', function() {
643+
var TestModel = loopback.createModel(uniqueModelName);
644+
loopback.configureModel(TestModel, {
645+
dataSource: null,
646+
methods: {
647+
staticMethod: {
648+
http: { path: '/static' }
649+
}
650+
}
651+
});
652+
653+
var methodNames = getAllMethodNamesWithoutClassName(TestModel);
654+
655+
expect(methodNames).to.include('staticMethod');
656+
});
657+
658+
it('treats method names starting with "prototype." as "isStatic:false"', function() {
659+
var TestModel = loopback.createModel(uniqueModelName);
660+
loopback.configureModel(TestModel, {
661+
dataSource: null,
662+
methods: {
663+
'prototype.instanceMethod': {
664+
http: { path: '/instance' }
665+
}
666+
}
667+
});
668+
669+
var methodNames = getAllMethodNamesWithoutClassName(TestModel);
670+
671+
expect(methodNames).to.include('prototype.instanceMethod');
672+
});
673+
674+
it('throws an error when "isStatic:true" and method name starts with "prototype."', function() {
675+
var TestModel = loopback.createModel(uniqueModelName);
676+
expect(function() { loopback.configureModel(TestModel, {
677+
dataSource: null,
678+
methods: {
679+
'prototype.instanceMethod': {
680+
isStatic: true,
681+
http: { path: '/instance' }
682+
}
683+
}
684+
});}).to.throw(Error, new Error('Remoting metadata for' + TestModel.modelName +
685+
' "isStatic" does not match new method name-based style.'));
686+
});
687+
688+
it('use "isStatic:true" if method name does not start with "prototype."', function() {
689+
var TestModel = loopback.createModel(uniqueModelName);
690+
loopback.configureModel(TestModel, {
691+
dataSource: null,
692+
methods: {
693+
staticMethod: {
694+
isStatic: true,
695+
http: { path: '/static' }
696+
}
697+
}
698+
});
699+
700+
var methodNames = getAllMethodNamesWithoutClassName(TestModel);
701+
702+
expect(methodNames).to.include('staticMethod');
703+
});
704+
705+
it('use "isStatic:false" if method name starts with "prototype."', function() {
706+
var TestModel = loopback.createModel(uniqueModelName);
707+
loopback.configureModel(TestModel, {
708+
dataSource: null,
709+
methods: {
710+
'prototype.instanceMethod': {
711+
isStatic: false,
712+
http: { path: '/instance' }
713+
}
714+
}
715+
});
716+
717+
var methodNames = getAllMethodNamesWithoutClassName(TestModel);
718+
719+
expect(methodNames).to.include('prototype.instanceMethod');
720+
});
721+
});
634722
});

0 commit comments

Comments
 (0)