Fix the datasource.define
This commit is contained in:
parent
8263a6d71b
commit
7caaeb2623
|
@ -1,21 +1,38 @@
|
||||||
var DataSource = require('../../jugglingdb').DataSource;
|
var DataSource = require('../../jugglingdb').DataSource;
|
||||||
var ds = new DataSource('memory');
|
var ds = new DataSource('memory');
|
||||||
|
|
||||||
|
var Article = ds.define('Article', {title: String});
|
||||||
|
var Tag = ds.define('Tag', {name: String});
|
||||||
|
Article.hasAndBelongsToMany('tags');
|
||||||
|
|
||||||
|
Article.create(function(e, article) {
|
||||||
|
article.tags.create({name: 'popular'}, function (err, data) {
|
||||||
|
Article.findOne(function(e, article) {
|
||||||
|
article.tags(function(e, tags) {
|
||||||
|
console.log(tags);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// define models
|
// define models
|
||||||
var Post = ds.define('Post', {
|
var Post = ds.define('Post', {
|
||||||
title: { type: String, length: 255 },
|
title: { type: String, length: 255 },
|
||||||
content: { type: DataSource.Text },
|
content: { type: DataSource.Text },
|
||||||
date: { type: Date, default: function () { return new Date;} },
|
date: { type: Date, default: function () {
|
||||||
timestamp: { type: Number, default: Date.now },
|
return new Date;
|
||||||
|
} },
|
||||||
|
timestamp: { type: Number, default: Date.now },
|
||||||
published: { type: Boolean, default: false, index: true }
|
published: { type: Boolean, default: false, index: true }
|
||||||
});
|
});
|
||||||
|
|
||||||
// simplier way to describe model
|
// simplier way to describe model
|
||||||
var User = ds.define('User', {
|
var User = ds.define('User', {
|
||||||
name: String,
|
name: String,
|
||||||
bio: DataSource.Text,
|
bio: DataSource.Text,
|
||||||
approved: Boolean,
|
approved: Boolean,
|
||||||
joinedAt: Date,
|
joinedAt: Date,
|
||||||
age: Number
|
age: Number
|
||||||
});
|
});
|
||||||
|
|
||||||
var Group = ds.define('Group', {name: String});
|
var Group = ds.define('Group', {name: String});
|
||||||
|
@ -28,9 +45,54 @@ User.prototype.getNameAndAge = function () {
|
||||||
var user = new User({name: 'Joe'});
|
var user = new User({name: 'Joe'});
|
||||||
console.log(user);
|
console.log(user);
|
||||||
|
|
||||||
console.log(ds.models);
|
// console.log(ds.models);
|
||||||
console.log(ds.definitions);
|
// console.log(ds.definitions);
|
||||||
|
|
||||||
|
// setup relationships
|
||||||
|
User.hasMany(Post, {as: 'posts', foreignKey: 'userId'});
|
||||||
|
|
||||||
|
// creates instance methods:
|
||||||
|
// user.posts(conds)
|
||||||
|
// user.posts.build(data) // like new Post({userId: user.id});
|
||||||
|
// user.posts.create(data) // build and save
|
||||||
|
|
||||||
|
Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
|
||||||
|
// creates instance methods:
|
||||||
|
// post.author(callback) -- getter when called with function
|
||||||
|
// post.author() -- sync getter when called without params
|
||||||
|
// post.author(user) -- setter when called with object
|
||||||
|
|
||||||
|
User.hasAndBelongsToMany('groups');
|
||||||
|
|
||||||
|
var user2 = new User({name: 'Smith'});
|
||||||
|
user2.save(function (err) {
|
||||||
|
console.log(user2);
|
||||||
|
var post = user2.posts.build({title: 'Hello world'});
|
||||||
|
post.save(function(err, data) {
|
||||||
|
console.log(err ? err: data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Post.findOne({where: {published: false}, order: 'date DESC'}, function (err, data) {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
User.create({name: 'Jeff'}, function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(data);
|
||||||
|
var post = data.posts.build({title: 'My Post'});
|
||||||
|
console.log(post);
|
||||||
|
});
|
||||||
|
|
||||||
|
User.create({name: 'Ray'}, function (err, data) {
|
||||||
|
console.log(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
var count = 5;
|
||||||
|
setInterval(function() {console.log(count--); if(!count) process.exit(0);}, 100);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2
index.js
2
index.js
|
@ -2,8 +2,8 @@ var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
exports.ADL = require('./lib/adl').Schema;
|
exports.ADL = require('./lib/adl').Schema;
|
||||||
exports.Schema = require('./lib/schema').Schema;
|
|
||||||
exports.DataSource = require('./lib/datasource').DataSource;
|
exports.DataSource = require('./lib/datasource').DataSource;
|
||||||
|
exports.Schema = exports.DataSource; // require('./lib/schema').Schema;
|
||||||
exports.ModelBaseClass = require('./lib/model.js');
|
exports.ModelBaseClass = require('./lib/model.js');
|
||||||
|
|
||||||
var baseSQL = './lib/sql';
|
var baseSQL = './lib/sql';
|
||||||
|
|
|
@ -225,9 +225,6 @@ function standartize(properties, settings) {
|
||||||
Schema.prototype.defineProperty = function (model, prop, params) {
|
Schema.prototype.defineProperty = function (model, prop, params) {
|
||||||
this.definitions[model].properties[prop] = params;
|
this.definitions[model].properties[prop] = params;
|
||||||
this.models[model].registerProperty(prop);
|
this.models[model].registerProperty(prop);
|
||||||
if (this.adapter.defineProperty) {
|
|
||||||
this.adapter.defineProperty(model, prop, params);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -60,7 +60,7 @@ util.inherits(DataSource, ADL);
|
||||||
|
|
||||||
// Copy over statics
|
// Copy over statics
|
||||||
for (var m in ADL) {
|
for (var m in ADL) {
|
||||||
if (!DataSource[m]) {
|
if (!DataSource.hasOwnProperty(m) && 'super_' !== m) {
|
||||||
DataSource[m] = ADL[m];
|
DataSource[m] = ADL[m];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,15 @@ DataSource.prototype.setup = function(name, settings) {
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
DataSource.prototype.define = function defineClass(className, properties, settings) {
|
DataSource.prototype.define = function defineClass(className, properties, settings) {
|
||||||
|
var args = slice.call(arguments);
|
||||||
|
|
||||||
|
if (!className) throw new Error('Class name required');
|
||||||
|
if (args.length == 1) properties = {}, args.push(properties);
|
||||||
|
if (args.length == 2) settings = {}, args.push(settings);
|
||||||
|
|
||||||
|
properties = properties || {};
|
||||||
|
settings = settings || {};
|
||||||
|
|
||||||
var NewClass = ADL.prototype.define.call(this, className, properties, settings);
|
var NewClass = ADL.prototype.define.call(this, className, properties, settings);
|
||||||
|
|
||||||
// inherit DataAccessObject methods
|
// inherit DataAccessObject methods
|
||||||
|
@ -203,6 +212,20 @@ DataSource.prototype.define = function defineClass(className, properties, settin
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define single property named `prop` on `model`
|
||||||
|
*
|
||||||
|
* @param {String} model - name of model
|
||||||
|
* @param {String} prop - name of propery
|
||||||
|
* @param {Object} params - property settings
|
||||||
|
*/
|
||||||
|
DataSource.prototype.defineProperty = function (model, prop, params) {
|
||||||
|
ADL.prototype.defineProperty.call(this, model, prop, params);
|
||||||
|
|
||||||
|
if (this.adapter.defineProperty) {
|
||||||
|
this.adapter.defineProperty(model, prop, params);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drop each model table and re-create.
|
* Drop each model table and re-create.
|
||||||
|
|
|
@ -241,7 +241,3 @@ function isdef(s) {
|
||||||
return s !== undef;
|
return s !== undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelBaseClass.prototype.dataSource = function(name, settings) {
|
|
||||||
require('./jutil').inherits(this.constructor, require('./dao'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
250
lib/railway.js
250
lib/railway.js
|
@ -1,250 +0,0 @@
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
var Schema = require('./schema').Schema;
|
|
||||||
|
|
||||||
var existsSync = fs.existsSync || path.existsSync;
|
|
||||||
|
|
||||||
if (global.railway) {
|
|
||||||
railway.orm._schemas = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function init(root) {
|
|
||||||
var railway, app, models;
|
|
||||||
|
|
||||||
if (typeof root !== 'object' || (root.constructor.name !== 'Compound' && root.constructor.name !== 'CompoundServer')) {
|
|
||||||
railway = global.railway;
|
|
||||||
app = global.app;
|
|
||||||
models = app.models;
|
|
||||||
} else {
|
|
||||||
railway = root;
|
|
||||||
app = railway.app;
|
|
||||||
root = railway.root;
|
|
||||||
models = railway.models;
|
|
||||||
}
|
|
||||||
|
|
||||||
railway.orm._schemas = [];
|
|
||||||
|
|
||||||
var confFile = (root || app.root) + '/config/database';
|
|
||||||
var config = {};
|
|
||||||
|
|
||||||
try {
|
|
||||||
var cf = require(confFile);
|
|
||||||
if (cf instanceof Array) cf = cf[0];
|
|
||||||
if (typeof cs === 'function') {
|
|
||||||
config = cs(railway);
|
|
||||||
} else {
|
|
||||||
config = cf[app.set('env')];
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Could not load config/database.{js|json|yml}');
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when driver name started with point - look for driver in app root (relative path)
|
|
||||||
if (config.driver && config.driver.match(/^\./)) {
|
|
||||||
config.driver = path.join(app.root, config.driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
var schema = new Schema(config && config.driver || 'memory', config);
|
|
||||||
schema.log = log;
|
|
||||||
|
|
||||||
if (!schema.adapter) throw new Error('Adapter is not defined');
|
|
||||||
|
|
||||||
if (schema.waitForConnect) {
|
|
||||||
schema.on('connected', function() {
|
|
||||||
loadSchema(schema, railway, app, models);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
loadSchema(schema, railway, app, models);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check validations and display warning
|
|
||||||
|
|
||||||
var displayWarning = false;
|
|
||||||
Object.keys(models).forEach(function (model) {
|
|
||||||
var Model = models[model];
|
|
||||||
if (Model._validations) {
|
|
||||||
displayWarning = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (displayWarning) {
|
|
||||||
var $ = railway.utils.stylize.$;
|
|
||||||
// require('util').puts($('WARNING:').bold.red + ' ' + $('I can see that you\'ve added validation to db/schema.js. However schema.js file is only used to describe database schema. Therefore validations configured in db/schema.js will be ignored.\nFor business logic (incl. validations) please create models as separate .js files here: app/models/*.js').yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadSchema(schema, railway, app, models) {
|
|
||||||
railway.orm._schemas.push(schema);
|
|
||||||
|
|
||||||
var context = prepareContext(models, railway, app, schema);
|
|
||||||
|
|
||||||
// run schema first
|
|
||||||
var schemaFile = (root || app.root) + '/db/schema.';
|
|
||||||
if (existsSync(schemaFile + 'js')) {
|
|
||||||
schemaFile += 'js';
|
|
||||||
} else if (existsSync(schemaFile + 'coffee')) {
|
|
||||||
schemaFile += 'coffee';
|
|
||||||
} else {
|
|
||||||
schemaFile = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schemaFile) {
|
|
||||||
var code = fs.readFileSync(schemaFile).toString();
|
|
||||||
if (schemaFile.match(/\.coffee$/)) {
|
|
||||||
code = require('coffee-script').compile(code);
|
|
||||||
}
|
|
||||||
var fn = new Function('context', 'require', 'with(context){(function(){' + code + '})()}');
|
|
||||||
fn(context, require);
|
|
||||||
}
|
|
||||||
|
|
||||||
// autoupdate if set app.enable('autoupdate') or freeze schemas by default
|
|
||||||
railway.orm._schemas.forEach(function (schema) {
|
|
||||||
if(app.enabled('autoupdate')){
|
|
||||||
schema.autoupdate();
|
|
||||||
} else {
|
|
||||||
schema.freeze();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function log(str, startTime) {
|
|
||||||
var $ = railway.utils.stylize.$;
|
|
||||||
var m = Date.now() - startTime;
|
|
||||||
railway.utils.debug(str + $(' [' + (m < 10 ? m : $(m).red) + ' ms]').bold);
|
|
||||||
app.emit('app-event', {
|
|
||||||
type: 'query',
|
|
||||||
param: str,
|
|
||||||
time: m
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareContext(models, railway, app, defSchema, done) {
|
|
||||||
var ctx = {app: app},
|
|
||||||
_models = {},
|
|
||||||
settings = {},
|
|
||||||
cname,
|
|
||||||
schema,
|
|
||||||
connected = 0,
|
|
||||||
wait = 0,
|
|
||||||
nonJugglingSchema = false;
|
|
||||||
|
|
||||||
done = done || function () {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Multiple schemas support
|
|
||||||
* example:
|
|
||||||
* schema('redis', {url:'...'}, function () {
|
|
||||||
* describe models using redis connection
|
|
||||||
* ...
|
|
||||||
* });
|
|
||||||
* schema(function () {
|
|
||||||
* describe models stored in memory
|
|
||||||
* ...
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
ctx.schema = function () {
|
|
||||||
var name = argument('string');
|
|
||||||
var opts = argument('object') || {};
|
|
||||||
var def = argument('function') || function () {};
|
|
||||||
schema = new Schema(name || opts.driver || 'memory', opts);
|
|
||||||
railway.orm._schemas.push(schema);
|
|
||||||
wait += 1;
|
|
||||||
ctx.gotSchema = true;
|
|
||||||
schema.on('log', log);
|
|
||||||
schema.on('connected', function () {
|
|
||||||
if (wait === ++connected) done();
|
|
||||||
});
|
|
||||||
def();
|
|
||||||
schema = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use custom schema driver
|
|
||||||
*/
|
|
||||||
ctx.customSchema = function () {
|
|
||||||
var def = argument('function') || function () {};
|
|
||||||
nonJugglingSchema = true;
|
|
||||||
def();
|
|
||||||
Object.keys(ctx.exports).forEach(function (m) {
|
|
||||||
ctx.define(m, ctx.exports[m]);
|
|
||||||
});
|
|
||||||
nonJugglingSchema = false;
|
|
||||||
};
|
|
||||||
ctx.exports = {};
|
|
||||||
ctx.module = { exports: ctx.exports };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define a class in current schema
|
|
||||||
*/
|
|
||||||
ctx.describe = ctx.define = function (className, callback) {
|
|
||||||
var m;
|
|
||||||
cname = className;
|
|
||||||
_models[cname] = {};
|
|
||||||
settings[cname] = {};
|
|
||||||
if (nonJugglingSchema) {
|
|
||||||
m = callback;
|
|
||||||
} else {
|
|
||||||
callback && callback();
|
|
||||||
m = (schema || defSchema).define(className, _models[cname], settings[cname]);
|
|
||||||
}
|
|
||||||
if (global.railway) {
|
|
||||||
global[cname] = m;
|
|
||||||
}
|
|
||||||
return models[cname] = ctx[cname] = m;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define a property in current class
|
|
||||||
*/
|
|
||||||
ctx.property = function (name, type, params) {
|
|
||||||
if (!params) params = {};
|
|
||||||
if (typeof type !== 'function' && typeof type === 'object' && !(type instanceof Array)) {
|
|
||||||
params = type;
|
|
||||||
type = String;
|
|
||||||
}
|
|
||||||
params.type = type || String;
|
|
||||||
_models[cname][name] = params;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set custom table name for current class
|
|
||||||
* @param name - name of table
|
|
||||||
*/
|
|
||||||
ctx.setTableName = function (name) {
|
|
||||||
if (cname) settings[cname].table = name;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set configuration param
|
|
||||||
*
|
|
||||||
* @param name - name of param.
|
|
||||||
* @param value - value.
|
|
||||||
*/
|
|
||||||
ctx.set = function (name, value) {
|
|
||||||
if (cname) settings[cname][name] = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.pathTo = railway.map && railway.map.pathTo || {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the Schema has additional types, add them to the context
|
|
||||||
* e.g. MySQL has an additional Point type
|
|
||||||
*/
|
|
||||||
if (Schema.types && Object.keys(Schema.types).length) {
|
|
||||||
for (var typeName in Schema.types) {
|
|
||||||
ctx[typeName] = Schema.types[typeName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
|
|
||||||
function argument(type) {
|
|
||||||
var r;
|
|
||||||
[].forEach.call(arguments.callee.caller.arguments, function (a) {
|
|
||||||
if (!r && typeof a === type) r = a;
|
|
||||||
});
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -5,7 +5,7 @@ var i8n = require('inflection');
|
||||||
var defineScope = require('./scope.js').defineScope;
|
var defineScope = require('./scope.js').defineScope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relations mixins for ./model.js
|
* Relations mixins for ./dao.js
|
||||||
*/
|
*/
|
||||||
var Model = require('./dao.js');
|
var Model = require('./dao.js');
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue