Skip to content

Commit

Permalink
feat: support subproperty for delegate (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
army8735 authored and dead-horse committed Aug 31, 2018
1 parent 7e0f9ac commit cc30ec2
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ services:
before_install:
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
- mysql -e 'CREATE DATABASE IF NOT EXISTS test1;'
- mysql -e 'CREATE DATABASE IF NOT EXISTS test2;'
- mysql -e 'CREATE DATABASE IF NOT EXISTS test3;'
24 changes: 17 additions & 7 deletions lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,32 @@ module.exports = app => {

const sequelize = new app.Sequelize(config.database, config.username, config.password, config);

if (app[config.delegate] || app.context[config.delegate]) {
throw new Error(`[egg-sequelize] app[${config.delegate}] or ctx[${config.delegate}] is already defined`);
const delegate = config.delegate.split('.');
const len = delegate.length;

let model = app;
let context = app.context;
for (let i = 0; i < len - 1; i++) {
model = model[delegate[i]] = model[delegate[i]] || {};
context = context[delegate[i]] = context[delegate[i]] || {};
}

Object.defineProperty(app, config.delegate, {
if (model[delegate[len - 1]]) {
throw new Error(`[egg-sequelize] app[${config.delegate}] is already defined`);
}

Object.defineProperty(model, delegate[len - 1], {
value: sequelize,
writable: false,
configurable: true,
});

const DELEGATE = Symbol(`context#sequelize_${config.delegate}`);
Object.defineProperty(app.context, config.delegate, {
Object.defineProperty(context, delegate[len - 1], {
get() {
// context.model is different with app.model
// so we can change the properties of ctx.model.xxx
if (!this[DELEGATE]) this[DELEGATE] = Object.create(app[config.delegate]);
if (!this[DELEGATE]) this[DELEGATE] = Object.create(model[delegate[len - 1]]);
return this[DELEGATE];
},
configurable: true,
Expand All @@ -92,13 +102,13 @@ module.exports = app => {
return true;
},
});
Object.assign(app[config.delegate], app[target]);
Object.assign(model[delegate[len - 1]], app[target]);

models.forEach(model => {
typeof model.associate === 'function' && model.associate();
});

return app[config.delegate];
return model[delegate[len - 1]];
}

/**
Expand Down
25 changes: 25 additions & 0 deletions test/datasources.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('test/datasources.test.js', () => {
before(async () => {
await app.model.sync({ force: true });
await app.sequelize.sync({ force: true });
await app.subproperty.a.sync({ force: true });
await app.subproperty.b.sync({ force: true });
});

after(mm.restore);
Expand All @@ -24,6 +26,8 @@ describe('test/datasources.test.js', () => {
assert(app.model);
assert(app.sequelize);
assert(app.Sequelize);
assert(app.subproperty.a);
assert(app.subproperty.b);
});

it('ctx model property getter', () => {
Expand All @@ -37,6 +41,15 @@ describe('test/datasources.test.js', () => {
assert(ctx.sequelize.Monkey);
assert(!ctx.sequelize.Person); // ignored
assert(ctx.model.User !== ctx.sequelize.User);
assert(ctx.subproperty.a);
assert(ctx.subproperty.a.User);
assert(ctx.subproperty.a.Monkey);
assert(ctx.subproperty.a.Person);
assert(ctx.subproperty.b);
assert(ctx.subproperty.b.User);
assert(ctx.subproperty.b.Monkey);
assert(ctx.subproperty.b.Person);
assert(ctx.subproperty.a.User !== ctx.subproperty.b.User);
});

it('has right tableName', () => {
Expand All @@ -45,6 +58,8 @@ describe('test/datasources.test.js', () => {
assert(app.model.Monkey.tableName === 'the_monkeys');
assert(app.sequelize.User.tableName === 'users');
assert(app.sequelize.Monkey.tableName === 'the_monkeys');
assert(app.subproperty.a.Monkey.tableName === 'the_monkeys');
assert(app.subproperty.b.Monkey.tableName === 'the_monkeys');
});
});

Expand Down Expand Up @@ -80,6 +95,16 @@ describe('test/datasources.test.js', () => {
assert.ok(ctx.sequelize.User);
assert.ok(ctx.sequelize.User.prototype.hasPosts);
assert.ok(ctx.sequelize.Post);

assert.ok(ctx.subproperty.a);
assert.ok(ctx.subproperty.a.User);
assert.ok(ctx.subproperty.a.User.prototype.hasPosts);
assert.ok(ctx.subproperty.a.Post);

assert.ok(ctx.subproperty.a);
assert.ok(ctx.subproperty.a.User);
assert.ok(ctx.subproperty.a.User.prototype.hasPosts);
assert.ok(ctx.subproperty.a.Post);
});
});
});
10 changes: 10 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/a/Person.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

module.exports = app => {
const { STRING } = app.Sequelize;
const Person = app.subproperty.a.define('person', {
name: STRING(30),
});

return Person;
};
28 changes: 28 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/a/monkey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const Monkey = app.subproperty.a.define('monkey', {
name: {
type: STRING,
allowNull: false,
},
user_id: INTEGER,
created_at: DATE,
updated_at: DATE,
}, {
tableName: 'the_monkeys',

classMethods: {
},

instanceMethods: {
},
});

Monkey.findUser = async function() {
return app.subproperty.a.User.find({ id: 1 });
};

return Monkey;
};
4 changes: 4 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/a/other.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use strict';

module.exports = {
};
19 changes: 19 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/a/post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const assert = require('assert');

module.exports = app => {
const { INTEGER, STRING } = app.Sequelize;
const Post = app.subproperty.a.define('post', {
user_id: INTEGER,
name: STRING(30),
});

Post.associate = function() {
assert.ok(app.subproperty.a.User);
assert.ok(app.subproperty.a.Post);
app.subproperty.a.Post.belongsTo(app.subproperty.a.User, { as: 'user', foreignKey: 'user_id' });
};

return Post;
};
28 changes: 28 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/a/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

const assert = require('assert');

module.exports = app => {
const { STRING, INTEGER } = app.Sequelize;
const User = app.subproperty.a.define('user', {
name: STRING(30),
age: INTEGER,
});

User.associate = function() {
assert.ok(app.subproperty.a.User);
assert.ok(app.subproperty.a.Post);
app.subproperty.a.User.hasMany(app.subproperty.a.Post, { as: 'posts', foreignKey: 'user_id' });
};

User.test = async function() {
assert(app.config);
assert(app.subproperty.a.User === this);
const monkey = await app.subproperty.a.Monkey.create({ name: 'The Monkey' });
assert(monkey.id);
assert(monkey.isNewRecord === false);
assert(monkey.name === 'The Monkey');
};

return User;
};
10 changes: 10 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/b/Person.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

module.exports = app => {
const { STRING } = app.Sequelize;
const Person = app.subproperty.b.define('person', {
name: STRING(30),
});

return Person;
};
28 changes: 28 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/b/monkey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const Monkey = app.subproperty.b.define('monkey', {
name: {
type: STRING,
allowNull: false,
},
user_id: INTEGER,
created_at: DATE,
updated_at: DATE,
}, {
tableName: 'the_monkeys',

classMethods: {
},

instanceMethods: {
},
});

Monkey.findUser = async function() {
return app.subproperty.b.User.find({ id: 1 });
};

return Monkey;
};
4 changes: 4 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/b/other.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
'use strict';

module.exports = {
};
19 changes: 19 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/b/post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const assert = require('assert');

module.exports = app => {
const { INTEGER, STRING } = app.Sequelize;
const Post = app.subproperty.b.define('post', {
user_id: INTEGER,
name: STRING(30),
});

Post.associate = function() {
assert.ok(app.subproperty.b.User);
assert.ok(app.subproperty.b.Post);
app.subproperty.b.Post.belongsTo(app.subproperty.b.User, { as: 'user', foreignKey: 'user_id' });
};

return Post;
};
28 changes: 28 additions & 0 deletions test/fixtures/apps/datasources/app/subproperty/b/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

const assert = require('assert');

module.exports = app => {
const { STRING, INTEGER } = app.Sequelize;
const User = app.subproperty.b.define('user', {
name: STRING(30),
age: INTEGER,
});

User.associate = function() {
assert.ok(app.subproperty.b.User);
assert.ok(app.subproperty.b.Post);
app.subproperty.b.User.hasMany(app.subproperty.b.Post, { as: 'posts', foreignKey: 'user_id' });
};

User.test = async function() {
assert(app.config);
assert(app.subproperty.b.User === this);
const monkey = await app.subproperty.b.Monkey.create({ name: 'The Monkey' });
assert(monkey.id);
assert(monkey.isNewRecord === false);
assert(monkey.name === 'The Monkey');
};

return User;
};
12 changes: 12 additions & 0 deletions test/fixtures/apps/datasources/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ exports.sequelize = {
dialect: 'mysql',
exclude: 'Person.js',
},
{
delegate: 'subproperty.a',
baseDir: 'subproperty/a',
database: 'test2',
dialect: 'mysql',
},
{
delegate: 'subproperty.b',
baseDir: 'subproperty/b',
database: 'test3',
dialect: 'mysql',
},
],
};

Expand Down

0 comments on commit cc30ec2

Please sign in to comment.