Tidy up model building from data sources
See https://github.com/strongloop/loopback/issues/560
This commit is contained in:
parent
3655107334
commit
fe74c8019c
|
@ -1427,6 +1427,7 @@ DataSource.prototype.discoverSchemasSync = function (modelName, options) {
|
|||
*/
|
||||
DataSource.prototype.discoverAndBuildModels = function (modelName, options, cb) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
this.discoverSchemas(modelName, options, function (err, schemas) {
|
||||
if (err) {
|
||||
cb && cb(err, schemas);
|
||||
|
@ -1436,14 +1437,16 @@ DataSource.prototype.discoverAndBuildModels = function (modelName, options, cb)
|
|||
var schemaList = [];
|
||||
for (var s in schemas) {
|
||||
var schema = schemas[s];
|
||||
if (options.base) {
|
||||
schema.options = schema.options || {};
|
||||
schema.options.base = options.base;
|
||||
}
|
||||
schemaList.push(schema);
|
||||
}
|
||||
|
||||
var models = self.modelBuilder.buildModels(schemaList);
|
||||
// Now attach the models to the data source
|
||||
for (var m in models) {
|
||||
models[m].attachTo(self);
|
||||
}
|
||||
var models = self.modelBuilder.buildModels(schemaList,
|
||||
self.createModel.bind(self));
|
||||
|
||||
cb && cb(err, models);
|
||||
});
|
||||
};
|
||||
|
@ -1462,18 +1465,41 @@ DataSource.prototype.discoverAndBuildModels = function (modelName, options, cb)
|
|||
* @param {Object} [options] The options
|
||||
*/
|
||||
DataSource.prototype.discoverAndBuildModelsSync = function (modelName, options) {
|
||||
options = options || {};
|
||||
var schemas = this.discoverSchemasSync(modelName, options);
|
||||
|
||||
var schemaList = [];
|
||||
for (var s in schemas) {
|
||||
var schema = schemas[s];
|
||||
if (options.base) {
|
||||
schema.options = schema.options || {};
|
||||
schema.options.base = options.base;
|
||||
}
|
||||
schemaList.push(schema);
|
||||
}
|
||||
|
||||
var models = this.modelBuilder.buildModels(schemaList);
|
||||
var models = this.modelBuilder.buildModels(schemaList,
|
||||
this.createModel.bind(this));
|
||||
|
||||
return models;
|
||||
};
|
||||
|
||||
/**
|
||||
* Introspect a JSON object and build a model class
|
||||
* @param {String} name Name of the model
|
||||
* @param {Object} json The json object representing a model instance
|
||||
* @param {Object} options Options
|
||||
* @returns {*}
|
||||
*/
|
||||
DataSource.prototype.buildModelFromInstance = function (name, json, options) {
|
||||
|
||||
// Introspect the JSON document to generate a schema
|
||||
var schema = ModelBuilder.introspect(json);
|
||||
|
||||
// Create a model for the generated schema
|
||||
return this.createModel(name, schema, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether migrations needed
|
||||
* This method applies only to SQL connectors.
|
||||
|
|
|
@ -24,12 +24,13 @@ module.exports = function getIntrospector(ModelBuilder) {
|
|||
return 'date';
|
||||
}
|
||||
|
||||
var itemType;
|
||||
if (Array.isArray(value)) {
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
if (value[i] === null || value[i] === undefined) {
|
||||
continue;
|
||||
}
|
||||
var itemType = introspectType(value[i]);
|
||||
itemType = introspectType(value[i]);
|
||||
if (itemType) {
|
||||
return [itemType];
|
||||
}
|
||||
|
@ -43,7 +44,7 @@ module.exports = function getIntrospector(ModelBuilder) {
|
|||
|
||||
var properties = {};
|
||||
for (var p in value) {
|
||||
var itemType = introspectType(value[p]);
|
||||
itemType = introspectType(value[p]);
|
||||
if (itemType) {
|
||||
properties[p] = itemType;
|
||||
}
|
||||
|
@ -54,6 +55,7 @@ module.exports = function getIntrospector(ModelBuilder) {
|
|||
return properties;
|
||||
}
|
||||
|
||||
ModelBuilder.introspect = introspectType;
|
||||
return introspectType;
|
||||
}
|
||||
|
||||
|
|
|
@ -632,7 +632,7 @@ ModelBuilder.prototype.resolveType = function (type) {
|
|||
* @param {*} schemas The schemas
|
||||
* @returns {Object} A map of model constructors keyed by model name
|
||||
*/
|
||||
ModelBuilder.prototype.buildModels = function (schemas) {
|
||||
ModelBuilder.prototype.buildModels = function (schemas, createModel) {
|
||||
var models = {};
|
||||
|
||||
// Normalize the schemas to be an array of the schema objects {name: <name>, properties: {}, options: {}}
|
||||
|
@ -656,7 +656,12 @@ ModelBuilder.prototype.buildModels = function (schemas) {
|
|||
for (var s in schemas) {
|
||||
var name = this.getSchemaName(schemas[s].name);
|
||||
schemas[s].name = name;
|
||||
var model = this.define(schemas[s].name, schemas[s].properties, schemas[s].options);
|
||||
var model;
|
||||
if(typeof createModel === 'function') {
|
||||
model = createModel(schemas[s].name, schemas[s].properties, schemas[s].options);
|
||||
} else {
|
||||
model = this.define(schemas[s].name, schemas[s].properties, schemas[s].options);
|
||||
}
|
||||
models[name] = model;
|
||||
relations = relations.concat(model.definition.relations);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,29 @@
|
|||
var assert = require('assert');
|
||||
var ModelBuilder = require('../lib/model-builder').ModelBuilder;
|
||||
var ModelBuilder = require('..').ModelBuilder;
|
||||
var DataSource = require('../').DataSource;
|
||||
var introspectType = require('../lib/introspection')(ModelBuilder);
|
||||
var traverse = require('traverse');
|
||||
|
||||
var json = {
|
||||
name: 'Joe',
|
||||
age: 30,
|
||||
birthday: new Date(),
|
||||
vip: true,
|
||||
address: {
|
||||
street: '1 Main St',
|
||||
city: 'San Jose',
|
||||
state: 'CA',
|
||||
zipcode: '95131',
|
||||
country: 'US'
|
||||
},
|
||||
friends: ['John', 'Mary'],
|
||||
emails: [
|
||||
{label: 'work', id: 'x@sample.com'},
|
||||
{label: 'home', id: 'x@home.com'}
|
||||
],
|
||||
tags: []
|
||||
};
|
||||
|
||||
describe('Introspection of model definitions from JSON', function () {
|
||||
|
||||
it('should handle simple types', function () {
|
||||
|
@ -61,27 +82,6 @@ describe('Introspection of model definitions from JSON', function () {
|
|||
});
|
||||
|
||||
it('should build a model from the introspected schema', function (done) {
|
||||
|
||||
var json = {
|
||||
name: 'Joe',
|
||||
age: 30,
|
||||
birthday: new Date(),
|
||||
vip: true,
|
||||
address: {
|
||||
street: '1 Main St',
|
||||
city: 'San Jose',
|
||||
state: 'CA',
|
||||
zipcode: '95131',
|
||||
country: 'US'
|
||||
},
|
||||
friends: ['John', 'Mary'],
|
||||
emails: [
|
||||
{label: 'work', id: 'x@sample.com'},
|
||||
{label: 'home', id: 'x@home.com'}
|
||||
],
|
||||
tags: []
|
||||
};
|
||||
|
||||
var copy = traverse(json).clone();
|
||||
|
||||
var schema = introspectType(json);
|
||||
|
@ -97,5 +97,33 @@ describe('Introspection of model definitions from JSON', function () {
|
|||
assert.deepEqual(obj, copy);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should build a model using buildModelFromInstance', function (done) {
|
||||
var copy = traverse(json).clone();
|
||||
|
||||
var builder = new ModelBuilder();
|
||||
var Model = builder.buildModelFromInstance('MyModel', copy, {idInjection: false});
|
||||
|
||||
var obj = new Model(json);
|
||||
obj = obj.toObject();
|
||||
assert.deepEqual(obj, copy);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should build a model using DataSource.buildModelFromInstance', function (done) {
|
||||
var copy = traverse(json).clone();
|
||||
|
||||
var builder = new DataSource('memory');
|
||||
var Model = builder.buildModelFromInstance('MyModel', copy,
|
||||
{idInjection: false});
|
||||
|
||||
assert.equal(Model.dataSource, builder);
|
||||
|
||||
var obj = new Model(json);
|
||||
obj = obj.toObject();
|
||||
assert.deepEqual(obj, copy);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -1418,7 +1418,6 @@ describe('DataAccessObject', function () {
|
|||
});
|
||||
|
||||
describe('Load models from json', function () {
|
||||
it('should be able to define models from json', function () {
|
||||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
|
@ -1428,18 +1427,22 @@ describe('Load models from json', function () {
|
|||
* @returns A map of schemas keyed by name
|
||||
*/
|
||||
function loadSchemasSync(schemaFile, dataSource) {
|
||||
var modelBuilder, createModel;
|
||||
// Set up the data source
|
||||
if (!dataSource) {
|
||||
dataSource = new DataSource('memory');
|
||||
modelBuilder = new ModelBuilder();
|
||||
} else {
|
||||
modelBuilder = dataSource.modelBuilder;
|
||||
createModel = dataSource.createModel.bind(dataSource);
|
||||
}
|
||||
|
||||
// Read the dataSource JSON file
|
||||
var schemas = JSON.parse(fs.readFileSync(schemaFile));
|
||||
|
||||
return dataSource.modelBuilder.buildModels(schemas);
|
||||
|
||||
return modelBuilder.buildModels(schemas, createModel);
|
||||
}
|
||||
|
||||
it('should be able to define models from json', function () {
|
||||
|
||||
var models = loadSchemasSync(path.join(__dirname, 'test1-schemas.json'));
|
||||
|
||||
models.should.have.property('AnonymousModel_0');
|
||||
|
@ -1459,6 +1462,16 @@ describe('Load models from json', function () {
|
|||
}
|
||||
});
|
||||
|
||||
it('should be able to define models from json using dataSource', function() {
|
||||
var ds = new DataSource('memory');
|
||||
|
||||
var models = loadSchemasSync(path.join(__dirname, 'test2-schemas.json'), ds);
|
||||
models.should.have.property('Address');
|
||||
models.should.have.property('Account');
|
||||
models.should.have.property('Customer');
|
||||
assert.equal(models.Address.dataSource, ds);
|
||||
});
|
||||
|
||||
it('should allow customization of default model base class', function () {
|
||||
var modelBuilder = new ModelBuilder();
|
||||
|
||||
|
|
Loading…
Reference in New Issue