Merge pull request #3858 from strongloop/feature/remove-model
feat: remove all references to a Model
This commit is contained in:
commit
7a148caa26
|
@ -163,6 +163,44 @@ app.model = function(Model, config) {
|
||||||
return Model;
|
return Model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all references to a previously registered Model.
|
||||||
|
*
|
||||||
|
* The method emits "modelDeleted" event as a counter-part to "modelRemoted"
|
||||||
|
* event.
|
||||||
|
*
|
||||||
|
* @param {String} modelName The name of the model to remove.
|
||||||
|
*/
|
||||||
|
app.deleteModelByName = function(modelName) {
|
||||||
|
const ModelCtor = this.models[modelName];
|
||||||
|
delete this.models[modelName];
|
||||||
|
delete this.models[classify(modelName)];
|
||||||
|
delete this.models[camelize(modelName)];
|
||||||
|
|
||||||
|
if (ModelCtor) {
|
||||||
|
ModelCtor.removeAllListeners();
|
||||||
|
|
||||||
|
const ix = this._models.indexOf(ModelCtor);
|
||||||
|
if (ix > -1) {
|
||||||
|
this._models.splice(ix, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const remotes = this.remotes();
|
||||||
|
remotes.deleteClassByName(modelName);
|
||||||
|
remotes.deleteTypeByName(modelName);
|
||||||
|
|
||||||
|
if (ModelCtor && ModelCtor.dataSource) {
|
||||||
|
ModelCtor.dataSource.deleteModelByName(modelName);
|
||||||
|
} else {
|
||||||
|
this.registry.modelBuilder.deleteModelByName(modelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearHandlerCache(this);
|
||||||
|
|
||||||
|
this.emit('modelDeleted', ModelCtor || modelName);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the models exported by the app. Returns only models defined using `app.model()`
|
* Get the models exported by the app. Returns only models defined using `app.model()`
|
||||||
*
|
*
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
"inflection": "^1.6.0",
|
"inflection": "^1.6.0",
|
||||||
"isemail": "^2.2.1",
|
"isemail": "^2.2.1",
|
||||||
"loopback-connector-remote": "^3.0.0",
|
"loopback-connector-remote": "^3.0.0",
|
||||||
"loopback-datasource-juggler": "^3.15.0",
|
"loopback-datasource-juggler": "^3.18.0",
|
||||||
"loopback-filters": "^1.0.0",
|
"loopback-filters": "^1.0.0",
|
||||||
"loopback-phase": "^3.0.0",
|
"loopback-phase": "^3.0.0",
|
||||||
"nodemailer": "^2.5.0",
|
"nodemailer": "^2.5.0",
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
"serve-favicon": "^2.2.0",
|
"serve-favicon": "^2.2.0",
|
||||||
"stable": "^0.1.5",
|
"stable": "^0.1.5",
|
||||||
"strong-globalize": "^3.1.0",
|
"strong-globalize": "^3.1.0",
|
||||||
"strong-remoting": "^3.0.0",
|
"strong-remoting": "^3.11.0",
|
||||||
"uid2": "0.0.3",
|
"uid2": "0.0.3",
|
||||||
"underscore.string": "^3.0.3"
|
"underscore.string": "^3.0.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,11 +17,12 @@ var describe = require('./util/describe');
|
||||||
var expect = require('./helpers/expect');
|
var expect = require('./helpers/expect');
|
||||||
var it = require('./util/it');
|
var it = require('./util/it');
|
||||||
var request = require('supertest');
|
var request = require('supertest');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
|
||||||
describe('app', function() {
|
describe('app', function() {
|
||||||
var app;
|
var app;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
app = loopback();
|
app = loopback({localRegistry: true, loadBuiltinModels: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.onServer('.middleware(phase, handler)', function() {
|
describe.onServer('.middleware(phase, handler)', function() {
|
||||||
|
@ -763,6 +764,66 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('app.deleteModelByName()', () => {
|
||||||
|
let TestModel;
|
||||||
|
beforeEach(setupTestModel);
|
||||||
|
|
||||||
|
it('removes the model from app registries', () => {
|
||||||
|
expect(Object.keys(app.models))
|
||||||
|
.to.contain('test-model')
|
||||||
|
.and.contain('TestModel')
|
||||||
|
.and.contain('testModel');
|
||||||
|
expect(app.models().map(m => m.modelName))
|
||||||
|
.to.contain('test-model');
|
||||||
|
|
||||||
|
app.deleteModelByName('test-model');
|
||||||
|
|
||||||
|
expect(Object.keys(app.models))
|
||||||
|
.to.not.contain('test-model')
|
||||||
|
.and.not.contain('TestModel')
|
||||||
|
.and.not.contain('testModel');
|
||||||
|
expect(app.models().map(m => m.modelName))
|
||||||
|
.to.not.contain('test-model');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes the model from juggler registries', () => {
|
||||||
|
expect(Object.keys(app.registry.modelBuilder.models))
|
||||||
|
.to.contain('test-model');
|
||||||
|
|
||||||
|
app.deleteModelByName('test-model');
|
||||||
|
|
||||||
|
expect(Object.keys(app.registry.modelBuilder.models))
|
||||||
|
.to.not.contain('test-model');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes the model from remoting registries', () => {
|
||||||
|
expect(Object.keys(app.remotes()._classes))
|
||||||
|
.to.contain('test-model');
|
||||||
|
|
||||||
|
app.deleteModelByName('test-model');
|
||||||
|
|
||||||
|
expect(Object.keys(app.remotes()._classes))
|
||||||
|
.to.not.contain('test-model');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('emits "modelDeleted" event', () => {
|
||||||
|
const spy = sinon.spy();
|
||||||
|
app.on('modelDeleted', spy);
|
||||||
|
|
||||||
|
app.deleteModelByName('test-model');
|
||||||
|
|
||||||
|
sinon.assert.calledWith(spy, TestModel);
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupTestModel() {
|
||||||
|
TestModel = app.registry.createModel({
|
||||||
|
name: 'test-model',
|
||||||
|
base: 'Model',
|
||||||
|
});
|
||||||
|
app.model(TestModel, {dataSource: null});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
describe('app.models', function() {
|
describe('app.models', function() {
|
||||||
it('is unique per app instance', function() {
|
it('is unique per app instance', function() {
|
||||||
app.dataSource('db', {connector: 'memory'});
|
app.dataSource('db', {connector: 'memory'});
|
||||||
|
|
|
@ -200,6 +200,18 @@ describe('loopback.rest', function() {
|
||||||
}, done);
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('rebuilds REST endpoints after a model was deleted', () => {
|
||||||
|
app.model(MyModel);
|
||||||
|
app.use(loopback.rest());
|
||||||
|
|
||||||
|
return request(app).get('/mymodels').expect(200)
|
||||||
|
.then(() => {
|
||||||
|
app.deleteModelByName('MyModel');
|
||||||
|
|
||||||
|
return request(app).get('/mymodels').expect(404);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function givenUserModelWithAuth() {
|
function givenUserModelWithAuth() {
|
||||||
var AccessToken = app.registry.getModel('AccessToken');
|
var AccessToken = app.registry.getModel('AccessToken');
|
||||||
app.model(AccessToken, {dataSource: 'db'});
|
app.model(AccessToken, {dataSource: 'db'});
|
||||||
|
|
Loading…
Reference in New Issue