Sails.js模型继承实现:如何让User与UserGroup继承Identity模型?
嘿,在Sails.js里实现User和UserGroup继承Identity模型的需求,其实有两种实用的方式,我给你详细讲讲:
方式一:使用Waterline原生模型继承(推荐)
Sails.js的核心ORM Waterline本身就支持模型继承,通过extends属性就能让子模型继承父模型的属性、生命周期钩子和方法,非常适合你的场景。
步骤1:创建通用的Identity模型
先在api/models/Identity.js里定义所有子模型需要共享的字段和逻辑:
module.exports = { attributes: { name: { type: 'string', required: true }, description: { type: 'string', allowNull: true }, // 通用时间字段,Waterline会自动维护 createdAt: { type: 'number', autoCreatedAt: true }, updatedAt: { type: 'number', autoUpdatedAt: true } }, // 通用的生命周期钩子,比如统一处理某些前置逻辑 beforeCreate: function(values, proceed) { // 比如给description设置默认值 if (!values.description) { values.description = '默认描述'; } return proceed(); } };
步骤2:让User模型继承Identity
在api/models/User.js里通过extends指定继承Identity,同时添加User独有的字段和逻辑:
module.exports = { // 指定继承的父模型 extends: 'Identity', attributes: { email: { type: 'string', required: true, unique: true }, password: { type: 'string', required: true }, // 这里可以添加User独有的关联,比如所属用户组 groups: { collection: 'usergroup', via: 'members' } }, // 重写父模型的钩子时,记得先调用父模型的逻辑 beforeCreate: async function(values, proceed) { try { // 先执行Identity的beforeCreate钩子 await sails.models.identity.beforeCreate(values, (err) => { if (err) throw err; }); // 再处理User自己的逻辑:加密密码 values.password = await sails.helpers.passwords.hashPassword(values.password); return proceed(); } catch (err) { return proceed(err); } } };
步骤3:让UserGroup模型继承Identity
同样的,在api/models/UserGroup.js里做类似操作:
module.exports = { extends: 'Identity', attributes: { // UserGroup独有的关联:成员列表 members: { collection: 'user', via: 'groups' }, // 其他独有的字段... } // 如果不需要重写钩子或添加新方法,这里可以只保留extends和attributes };
注意事项
- 继承后,子模型的数据库表会自动包含父模型的所有字段,父模型不会单独生成表
- 子模型可以覆盖父模型的属性定义(比如把父模型的
name从必填改成可选) - 如果子模型重写了父模型的生命周期钩子,一定要手动调用父模型的钩子逻辑,避免丢失通用处理
方式二:组合模式+生命周期钩子(复杂场景备选)
如果你的需求更复杂(比如Identity需要独立存储、被多个模型共享且需要单独维护),可以用组合模式:让User和UserGroup通过关联引用Identity,再通过生命周期钩子和自定义方法模拟“继承”的效果。
示例实现
- 先保留独立的Identity模型(会生成单独的数据库表):
// api/models/Identity.js module.exports = { attributes: { name: { type: 'string', required: true }, description: { type: 'string', allowNull: true }, createdAt: { type: 'number', autoCreatedAt: true }, updatedAt: { type: 'number', autoUpdatedAt: true } } };
- User模型通过
model关联Identity,并用钩子自动创建关联记录:
// api/models/User.js module.exports = { attributes: { identity: { model: 'identity', required: true, unique: true }, email: { type: 'string', required: true, unique: true }, password: { type: 'string', required: true } }, // 创建User时自动创建对应的Identity记录 beforeCreate: async function(values, proceed) { try { // 提取Identity需要的字段 const identityData = { name: values.name, description: values.description }; // 创建Identity并关联 const identity = await Identity.create(identityData).fetch(); values.identity = identity.id; // 处理密码加密 values.password = await sails.helpers.passwords.hashPassword(values.password); return proceed(); } catch (err) { return proceed(err); } }, // 自定义toJSON方法,把Identity的字段合并到User返回结果中,模拟继承的效果 customToJSON: function() { const obj = this.toObject(); // 如果已经populate了identity,就把字段合并进去 if (obj.identity) { obj.name = obj.identity.name; obj.description = obj.identity.description; delete obj.identity; } return obj; } };
这种方式的好处是Identity可以独立管理,适合需要复用Identity到更多模型的场景,但实现起来比原生继承繁琐一些。
内容的提问来源于stack exchange,提问作者Ppp
相关产品推荐
相关产品推荐

