12

I'm trying to get Loopback to discover and build my first table. I've used the simple example on their page at the bottom here:

http://docs.strongloop.com/display/LB/Database+discovery+API#DatabasediscoveryAPI-Exampleofbuildingmodelsviadiscovery

and I see the output of the table I'm discovering, but the API Explorer doesn't show the table or any newly generated endpoints. Also, the model-config.js file is not updated with the new table object. Here is the basic section of the code done on server start:

var loopback = require('loopback');
var boot = require('loopback-boot');
var DataSource = require('loopback-datasource-juggler').DataSource;
var mysqlSource = require('./datasources.json');
var dataSource = new DataSource('mssql', mysqlSource.mysqlserver);

var app = module.exports = loopback();

// Set up the /favicon.ico
app.use(loopback.favicon());

// request pre-processing middleware
app.use(loopback.compress());

// -- Add your pre-processing middleware here --

dataSource.discoverAndBuildModels('CATS', {owner: 'mamacat'}, function (err, models) {
    models.Cat.find(function (err, cat) {
        if (err) {
            console.error(err);
        } else {
            console.log(cat);
        }
        dataSource.disconnect();
    });
});

// boot scripts mount components like REST API
boot(app, __dirname);

To summarize, this runs, no errors. But no new models show on http://localhost:3000/explorer

Organiccat
  • 5,633
  • 17
  • 57
  • 104
  • Thanks, I just whipped out the name to replace my actual datasource for display purposes. It is using the right driver type, just bad naming on my part. – Organiccat Sep 30 '14 at 19:18
  • I also observed the same thing but the reason was that I used model's base class as 'Model' instead of 'PersistedModel' – Gagan Nov 21 '14 at 12:16
  • I have the same problem. I am discovering in server/boot/discover.js and get the same results. – Ran Regev Feb 12 '15 at 09:59

4 Answers4

12

Seems that discovery scripts only shows the output and doesn't create the model files. I found some instructions on loopback docs:

http://docs.strongloop.com/display/public/LB/Discovering+models+from+relational+databases

In section Basic Procedure, the second step:

2. Use fs.writeFile() to save the output in common/models/model-name.json.

So you can try the following approach:

  1. Setup your mysql data in yourloopbackproject/server/datasources.json file:
{
  "db": {
    "name": "db",
    "connector": "memory"
  },
  "accountDs": {
    "host": "mysqlServerName",
    "port": 3306,
    "database": "databaseName",
    "username": "username",
    "password": "password!",
    "name": "accountDs",
    "connector": "mysql"
  }
}
  1. Create the models folder if doesn't exist: yourloopbackproject/common/models.

  2. Create discovery-and-build.js script on yourloopbackproject/server/bin folder:

var path = require('path');
var fs = require('fs');
var app = require(path.resolve(__dirname, '../server'));
var outputPath = path.resolve(__dirname, '../../common/models');

var dataSource = app.dataSources.accountDs;

function schemaCB(err, schema) {
  if(schema) {
    console.log("Auto discovery success: " + schema.name);
    var outputName = outputPath + '/' +schema.name + '.json';
    fs.writeFile(outputName, JSON.stringify(schema, null, 2), function(err) {
      if(err) {
        console.log(err);
      } else {
        console.log("JSON saved to " + outputName);
      }
    });
  }
  if(err) {
    console.error(err);
    return;
  }
  return;
};

dataSource.discoverSchema('tableName',{schema:'schemaName'},schemaCB);

This script is based on: http://www.reddit.com/r/strongloop/comments/2upy76/autodiscoveryjs_recipe/

  1. After the script execution you will find a .json file on models folder. Go to step 3 on Basic Procedure section: http://docs.strongloop.com/display/public/LB/Discovering+models+from+relational+databases

  2. Follow these steps to expose your model over REST: http://docs.strongloop.com/display/public/LB/Exposing+models+over+REST

I hope this helps!

Ariskay
  • 168
  • 1
  • 7
  • This line seems doesn't works. `var app = require(path.resolve(__dirname, '../server'));` – richardaum Nov 18 '15 at 13:37
  • mmm that is weird. There is any error message on execution ? I was testing the code and have no problems executing this line. The script must be located in the bin folder on "yourloopbackproject/server/bin". BTW as @Anoop.P.A commented you can use arc to discover the models. :) – Ariskay Nov 18 '15 at 22:05
  • 1
    And pass ```associations : true``` for including table relations – JacopKane Mar 27 '16 at 23:01
  • 2
    you mean relations: true – jomicobasi Jul 11 '16 at 14:57
3

Use Arc for this. Run slc arc from the project folder and it will show up the gui tool called arc in default browser. If you've not already registered, sign up and log in. You will be directed to GUI tool of StrongLoop, the Arc. Select your model from list on the left pane. You'll be able to see save and migrate button. Just click the migrate button and your table will be created into model.(within millisecs!)

Cheers!

Anoop Thiruonam
  • 2,567
  • 2
  • 28
  • 48
  • 1
    While this is quite easier than writing a script it doesn't have any option to include relations between tables. – JacopKane Mar 27 '16 at 23:00
1

discovery api is used to only discover the schema not to create models for now. please use the following project to create models with one to one and one to many relationships and all the models.

https://github.com/savsharma2/loopback-sql-create-model-with-relation/

0

Building off of @Underskay's answer, I did something like

var fs = require('fs');
var app = require(__dirname + '/server/server');

function makePromise(f, parent) {
    return function(...args) {
        return new Promise((resolve, reject) => {
            f.call(parent, ...args, (err, ...data) => {
                if (err) return reject(err);
                resolve(data.length === 1 ? data[0] : data);
            });
        });
    };
}

var readFile = makePromise(fs.readFile, fs);
var writeFile = makePromise(fs.writeFile, fs);

function writeSchemas(schemas) {
    return Promise.all(schemas.map(data => {
        var schema = data[Object.keys(data)[0]];
        return writeFile('common/models/' + schema.name + '.json', JSON.stringify(schema, null, '\t'));
    }))
        .then(() => readFile('server/model-config.json'))
        .then(JSON.parse)
        .then(conf => {
            for (let schema of schemas)
                conf[schema[Object.keys(schema)[0]].name] = { "dataSource": "mysql" };
            return conf;
        })
        .then(conf => writeFile('server/model-config.json', JSON.stringify(conf, null, '\t')));
}

function getSchemas(ds) {
    var discoverSchemas = makePromise(ds.discoverSchemas, ds);
    return makePromise(ds.discoverModelDefinitions, ds)({})
        .then(tables => Promise.all(tables.map(t => discoverSchemas(t.name, { relations: true }))))
        .then(data => { ds.disconnect(); return data; });
}

Promise.resolve(app.datasources.mysql)
    .then(ds => getSchemas(ds))
    .then(schemas => writeSchemas(schemas))
    .catch(err => log.error(err));
Community
  • 1
  • 1
Iiridayn
  • 1,747
  • 21
  • 43