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

Commit 6bb91833 by Jan Aagaard Meier

[ci skip] Removed some unnecesary code in getter documentation. Closes #2775

1 parent e8d2336f
Showing with 30 additions and 62 deletions
......@@ -56,7 +56,7 @@ The comment option can also be used on a table, see [model configuration][0]
## Data types
Sequelize currently supports the following datatypes:
Below are some of the datatypes supported by sequelize. For a full and updated list, see [DataTypes](api/datatypes).
```js
Sequelize.STRING // VARCHAR(255)
......@@ -122,14 +122,14 @@ sequelize.define('model', {
## Getters & setters
It is possible to define 'object-property' getters and setter functions on your models, these can be used both for 'protecting' properties that map to database fields and for defining 'pseudo' properties.
It is possible to define 'object-property' getters and setter functions on your models, these can be used both for 'protecting' properties that map to database fields and for defining 'pseudo' properties.
Getters and Setters can be defined in 2 ways (you can mix and match these 2 approaches!):
Getters and Setters can be defined in 2 ways (you can mix and match these 2 approaches):
* as part of a single property definition
* as part of a model options
**N.B.:**If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence.
**N.B:** If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence.
### Defining as part of a property
......@@ -139,7 +139,8 @@ var Employee = sequelize.define('Employee', {
type : Sequelize.STRING,
allowNull: false,
get : function() {
var title = this.getDataValue('title'); // 'this' allows you to access attributes of the instance
var title = this.getDataValue('title');
// 'this' allows you to access attributes of the instance
return this.getDataValue('name') + ' (' + title + ')';
},
},
......@@ -162,53 +163,33 @@ Employee
### Defining as part of the model options
Below is an example of defining the getters and setters in the model options, notice the `title_slugslug` getter, it shows how you can define `pseudo` properties on your models! (the `slugify()` function was taken from the [Underscore.String module][1], it is slightly modified here so that the example remains self-contained), note that the `this.title` reference in the `title_slug` getter function will trigger a call to the `title` getter function. if you do not want that then use the `getDataValue()` method ([see below][2]).
Below is an example of defining the getters and setters in the model options. The `fullName` getter, is an example of how you can define pseudo properties on your models - attributes which are not actually part of your database schema. In fact, pseudo properties can be defined in two ways: using model getters, or by using a column with the [`VIRTUAL` datatype](api/datatypes#virtual). Virtual datatypes can have validations, while getters for virtual attributes cannot.
```js
var defaultToWhiteSpace = function(characters) {
if (characters == null)
return '\\s';
else if (characters.source)
return characters.source;
else
return ;
};
var slugify = function(str) {
var from = "ąàáäâãåæćęèéëêìíïîłńòóöôõøśùúüûñçżź",
to = "aaaaaaaaceeeeeiiiilnoooooosuuuunczz",
regex = new RegExp('[' + from.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1') + ']', 'g');
if (str == null) return '';
str = String(str).toLowerCase().replace(regex, function(c) {
return to.charAt(from.indexOf(c)) || '-';
});
return str.replace(/[^\w\s-]/g, '').replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
}
Note that the `this.firstname` and `this.lastname` references in the `fullName` getter function will trigger a call to the respective getter functions. If you do not want that then use the `getDataValue()` method to access the raw value (see below).
```js
var Foo = sequelize.define('Foo', {
title: {
type : Sequelize.STRING,
allowNull: false,
}
firstname: Sequelize.STRING,
lastname: Sequelize.STRING
}, {
getterMethods : {
title : function() { /* do your magic here and return something! */ },
title_slug : function() { return slugify(this.title); }
fullName : function() { return this.firstname + ' ' + this.lastname }
},
setterMethods : {
title : function(v) { /* do your magic with the input here! */ },
fullName : function(value) {
var names = value.split(' ');
this.setDataValue('firstname', names.slice(0, -1).join(' '));
this.setDataValue('lastname', names.slice(-1).join(' '));
},
}
});
```
### Helper functions for use inside getter/setter definitions
### Helper functions for use inside getter and setter definitions
* retrieving an underlying property value? always use `this.getDataValue()`, e.g:
* retrieving an underlying property value - always use `this.getDataValue()`
```js
/* a getter for 'title' property */
......@@ -217,7 +198,7 @@ function() {
}
```
* setting an underlying property value? always use `this.setDataValue()`, e.g.:
* setting an underlying property value - always use `this.setDataValue()`
```js
/* a setter for 'title' property */
......@@ -226,7 +207,7 @@ function(title) {
}
```
**N.B.: **It is important to stick to using the `setDataValue()` and `getDataValue()` functions (as opposed to accessing the underlying "data values" property directly) - doing so protects your custom getters and setters from changes in the underlying model implementations (i.e. how and where data values are stored in your model instances)
**N.B:** It is important to stick to using the `setDataValue()` and `getDataValue()` functions (as opposed to accessing the underlying "data values" property directly) - doing so protects your custom getters and setters from changes in the underlying model implementations.
## Validations
......@@ -785,7 +766,7 @@ Project.findAll({group: 'name'})
// yields GROUP BY name
```
Notice how in the two examples above, the string provided is inserted verbatim into the query, i.e. column names are not escaped. When you provide a string to order / group, this will always be the case as per v 1.7.0. If you want to escape column names, you should provide an array of arguments, even though you only want to order / group by a single column
Notice how in the two examples above, the string provided is inserted verbatim into the query, i.e. column names are not escaped. When you provide a string to order / group, this will always be the case. If you want to escape column names, you should provide an array of arguments, even though you only want to order / group by a single column
```js
something.find({
......@@ -821,10 +802,11 @@ To recap, the elements of the order / group array can be the following
### Raw queries
Sometimes you might be expecting a massive dataset that you just want to display, without manipulation. For each row you select, Sequelize creates a_DAO_, with functions for update, delete, get associations etc. If you have thousands of rows, this might take some time. If you only need the raw data and don't want to update anything, you can do like this to get the raw data.
Sometimes you might be expecting a massive dataset that you just want to display, without manipulation. For each row you select, Sequelize creates an instance with functions for updat, delete, get associations etc. If you have thousands of rows, this might take some time. If you only need the raw data and don't want to update anything, you can do like this to get the raw data.
```js
// Are you expecting a masssive dataset from the DB, and don't want to spend the time building DAOs for each entry?
// Are you expecting a masssive dataset from the DB,
// and don't want to spend the time building DAOs for each entry?
// You can pass an extra query option to get the raw data instead:
Project.findAll({ where: ... }, { raw: true })
```
......@@ -906,7 +888,7 @@ Project.sum('age', { where: { age: { $gt: 5 } } }).then(function(sum) {
## Eager loading
When you are retrieving data from the database there is a fair chance that you also want to get their associations. This is possible since`v1.6.0`and is called eager loading. The basic idea behind that, is the use of the attribute `include` when you are calling `find` or `findAll`. Lets assume the following setup:
When you are retrieving data from the database there is a fair chance that you also want to get associations with the same query - this is called eager loading. The basic idea behind that, is the use of the attribute `include` when you are calling `find` or `findAll`. Lets assume the following setup:
```js
var User = sequelize.define('User', { name: Sequelize.STRING })
......@@ -974,7 +956,7 @@ User.findAll({ include: [ Task ] }).then(function(users) {
Notice that the accessor is plural. This is because the association is many-to-something.
If an association is aliased (using the`as`option), you must specify this alias when including the model. Notice how the user's `Tool`s are aliased as `Instruments` above. In order to get that right you have to specify the model you want to load, as well as the alias:
If an association is aliased (using the `as` option), you must specify this alias when including the model. Notice how the user's `Tool`s are aliased as `Instruments` above. In order to get that right you have to specify the model you want to load, as well as the alias:
```js
User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(function(users) {
......@@ -1056,21 +1038,8 @@ User.findAll({
})
```
**Final note:**If you include an object which is not associated, Sequelize will throw an error.
```js
Tool.findAll({ include: [ User ] }).then(function(tools) {
console.log(JSON.stringify(tools))
})
// Error: User is not associated to Tool!
```
[0]: #configuration
[1]: https://github.com/epeli/underscore.string
[2]: #get_and_set_helper_funcs
[3]: https://github.com/chriso/validator.js
[4]: https://github.com/chriso/node-validator
[5]: /docs/latest/misc#asynchronicity
......
......@@ -452,8 +452,7 @@ util.inherits(UUIDV4, ABSTRACT);
UUIDV4.prototype.key = UUIDV4.key = 'UUIDV4';
/**
* A virtual value that is not stored in the DB. This could for example be useful if you want to provide a default value in your model
* that is returned to the user but not stored in the DB.
* A virtual value that is not stored in the DB. This could for example be useful if you want to provide a default value in your model that is returned to the user but not stored in the DB.
*
* You could also use it to validate a value before permuting and storing it. Checking password length before hashing it for example:
* ```js
......@@ -462,7 +461,7 @@ UUIDV4.prototype.key = UUIDV4.key = 'UUIDV4';
* password: {
* type: DataTypes.VIRTUAL,
* set: function (val) {
* this.setDataValue('password', val);
* this.setDataValue('password', val); // Remember to set the data value, otherwise it won't be validated
* this.setDataValue('password_hash', this.salt + val);
* },
* validate: {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!