-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I'm just throwing this in here to fuel some much needed discussion regarding the state of mixins, and what they could do for Loopback. I'm already using them extensively in my projects, and they allow distinct traits to be easily shared amongst models, and to be configured as needed.
When I see something like this #1260 - I see a problem that just begs for a Mixin to be implemented. Given the right infrastructure like the new operation hooks, there's a lot you can do.
Most of this has been available since loopbackio/loopback-datasource-juggler#201 ... but there's a pending discussion here: strongloop/loopback-boot#79
This is a bit from an model I've been using in one of my projects, post.js:
function setup(app) {
this.defineProperty('info', 'MetaData');
this.hasMany('Note', { as: 'notes', scope: { order: 'createdAt' } });
this.referencesMany('Employee', { as: 'authors' });
this.scope('galleries', { where: { type: 'Gallery' } });
this.mixin('ObjectId');
this.mixin('Protect', { properties: ['slug', 'type'] });
this.mixin('Alias', { property: 'slug', from: 'title' });
this.mixin('Transform', { property: 'type', filters: ['urlify', 'classify'] });
this.mixin('TimeStamps');
this.mixin('Storage', { as: 'attachments', references: true, relation: {
foreignKey: 'attachmentIds', scope: { order: 'filename' } }
});
this.mixin('Includes');
this.mixin('Reorder', { rel: 'attachments' });
this.mixin('Constraint', { rel: 'notes', action: 'delete' });
this.mixin('Versions', { attributes: ['title', 'body'], locale: true });
this.mixin('Search', { index: 'main' });
this.mixin('Expose', { scope: { order: 'slug' } });
this.mixin('Render');
this.mixin('Forms', { exclude: ['createdAt', 'updatedAt'] });
this.mixin('Virtuals', { methods: {
summary: function() {
return 'Summary: ' + this.title;
}
} });
};
module.exports = function(Post) {
Post.on('attached', setup.bind(Post));
};And the post.json:
{
"name": "Post",
"base": "PersistedModel",
"properties": {
"type": {
"type": "string",
"required": true,
"default": "Post",
"search": {
"index": "not_analyzed"
}
},
"title": {
"type": "string",
"required": true,
"search": {
"raw": true
}
},
"body": {
"type": "string",
"required": true
},
"active": {
"type": "boolean",
"default": true
}
},
"validations": [],
"relations": {
"sections": {
"type": "embedsMany",
"model": "Section"
}
},
"acls": [],
"methods": []
}Note that there's no pseudo code in there - this all works, and has been tested extensively.
Alternatively, you can declare mixins in your post.json under the mixins key like this:
{
"name": "Post",
"base": "PersistedModel",
"properties": { ... },
"mixins": {
"Protect": { "properties": ["slug", "type"] },
"Transform": [
{ "property": "name", "filters": ["capitalize"] },
{ "property": "type", "filters": ["urlify", "classify"] }
]
}
}