Merge pull request #3858 from strongloop/feature/remove-model

feat: remove all references to a Model
This commit is contained in:
Miroslav Bajtoš 2018-04-17 10:07:47 +02:00 committed by GitHub
commit 7a148caa26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 3 deletions

View File

@ -163,6 +163,44 @@ app.model = function(Model, config) {
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()`
*

View File

@ -49,7 +49,7 @@
"inflection": "^1.6.0",
"isemail": "^2.2.1",
"loopback-connector-remote": "^3.0.0",
"loopback-datasource-juggler": "^3.15.0",
"loopback-datasource-juggler": "^3.18.0",
"loopback-filters": "^1.0.0",
"loopback-phase": "^3.0.0",
"nodemailer": "^2.5.0",
@ -57,7 +57,7 @@
"serve-favicon": "^2.2.0",
"stable": "^0.1.5",
"strong-globalize": "^3.1.0",
"strong-remoting": "^3.0.0",
"strong-remoting": "^3.11.0",
"uid2": "0.0.3",
"underscore.string": "^3.0.3"
},

View File

@ -17,11 +17,12 @@ var describe = require('./util/describe');
var expect = require('./helpers/expect');
var it = require('./util/it');
var request = require('supertest');
const sinon = require('sinon');
describe('app', function() {
var app;
beforeEach(function() {
app = loopback();
app = loopback({localRegistry: true, loadBuiltinModels: true});
});
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() {
it('is unique per app instance', function() {
app.dataSource('db', {connector: 'memory'});

View File

@ -200,6 +200,18 @@ describe('loopback.rest', function() {
}, 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() {
var AccessToken = app.registry.getModel('AccessToken');
app.model(AccessToken, {dataSource: 'db'});