不要怂,就是干,撸起袖子干!

Commit c9edd420 by Jan Aagaard Meier

feature(scopes) addScope. Closes #3963

1 parent 2d3360cd
......@@ -5,6 +5,7 @@
- [FIXED] Call `conformOptions` on default scope [#4157](https://github.com/sequelize/sequelize/issues/4157)
- [FIXED] Call `conformOptions` on scopes returned by functions [#3991](https://github.com/sequelize/sequelize/issues/3991)
- [FIXED] Calling `validateIncludedElements` should not add an aliassed primary key multiple times [#4127](https://github.com/sequelize/sequelize/issues/4127)
- [FEATURE] `addScope` [#3963](https://github.com/sequelize/sequelize/issues/3963)
# 3.4.1
- [FIXED] Fix belongs-to-many `countAssociations` - ambigious id when through model has id
......
......@@ -43,6 +43,8 @@ var Project = sequelize.define('project', {
});
```
You can also add scopes after a model has been defined by calling `addScope`. This is especially useful for scopes with includes, where the model in the include might not be defined at the time the other model is being defined.
The default scope is always applied. This means, that with the model definition above, `Project.findAll()` will create the following query:
```sql
......
......@@ -1008,6 +1008,34 @@ Model.prototype.unscoped = function () {
};
/**
* Add a new scope to the model. This is especially useful for adding scopes with includes, when the model you want to include is not available at the time this model is defined.
*
* By default this will throw an error if a scope with that name already exists. Pass `override: true` in the options object to silence this error.
*
* @param {String} name The name of the scope. Use `defaultScope` to override the default scope
* @param {Object|Function} scope
* @param {Object} [options]
* @param {Boolean} [options.override=false]
*/
Model.prototype.addScope = function (name, scope, options) {
options = _.assign({
override: false
}, options);
if ((name === 'defaultScope' || name in this.options.scopes) && options.override === false) {
throw new Error('The scope ' + name + ' already exists. Pass { override: true } as options to silence this error');
}
conformOptions(scope);
if (name === 'defaultScope') {
this.options.defaultScope = this.$scope = scope;
} else {
this.options.scopes[name] = scope;
}
};
/**
* Apply a scope created in `define` to the model. First let's look at how to create scopes:
* ```js
* var Model = sequelize.define('model', attributes, {
......
......@@ -157,6 +157,61 @@ describe(Support.getTestDialectTeaser('Model'), function() {
});
});
describe('addScope', function () {
it('allows me to add a new scope', function () {
expect(function () {
Company.scope('newScope');
}).to.throw('Invalid scope newScope called.');
Company.addScope('newScope', {
where: {
this: 'that'
},
include: [Project]
});
expect(Company.scope('newScope').$scope).to.deep.equal({
where: { this: 'that' },
include: [{ model: Project }]
});
});
it('warns me when overriding an existing scope', function () {
expect(function () {
Company.addScope('somethingTrue', {});
}).to.throw('The scope somethingTrue already exists. Pass { override: true } as options to silence this error');
});
it('allows me to override an existing scope', function () {
Company.addScope('somethingTrue', {
where: {
something: false
}
}, { override: true });
expect(Company.scope('somethingTrue').$scope).to.deep.equal({
where: { something: false },
});
});
it('warns me when overriding an existing default scope', function () {
expect(function () {
Company.addScope('defaultScope', {});
}).to.throw('The scope defaultScope already exists. Pass { override: true } as options to silence this error');
});
it('allows me to override a default scope', function () {
Company.addScope('defaultScope', {
include: [Project]
}, { override: true });
console.log(Company.$scope);
expect(Company.$scope).to.deep.equal({
include: [{ model: Project }]
});
});
});
describe('$injectScope', function () {
it('should be able to merge scope and where', function () {
var scope = {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!