Fix(crud) include param lookup now works w/plurals
Previously, {one,many}-to-many relationships with models would result in `associationNames` that were plural. e.g. `Team` might have many players and one location. The validation was expecting to see the plural `Players` and the singular `Location` but Sequelize is expecting the singular `Player` (`Location` worked fine). This meant that include lookups would silently fail. This fixes the problem in a backward- compatible way. It continues to allow `include=Location` (capitalized) for backward- compatibility. And now allows and actually does the lookup for `include=players`, `include=player`, `include=Player`, `include=Players` lookup relationships.
This commit is contained in:
parent
07176018b7
commit
bcb7861061
13
README.md
13
README.md
@ -109,7 +109,7 @@ Getting related models is easy, just use a query parameter `include`.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// returns all teams with their related City model
|
// returns all teams with their related City model
|
||||||
// GET /teams?include=City
|
// GET /teams?include=city
|
||||||
|
|
||||||
// results in a Sequelize query:
|
// results in a Sequelize query:
|
||||||
Team.findAll({include: City})
|
Team.findAll({include: City})
|
||||||
@ -118,12 +118,21 @@ Team.findAll({include: City})
|
|||||||
If you want to get multiple related models, just pass multiple `include` parameters.
|
If you want to get multiple related models, just pass multiple `include` parameters.
|
||||||
```js
|
```js
|
||||||
// returns all teams with their related City and Uniform models
|
// returns all teams with their related City and Uniform models
|
||||||
// GET /teams?include=City&include=Uniform
|
// GET /teams?include[]=city&include[]=uniform
|
||||||
|
|
||||||
// results in a Sequelize query:
|
// results in a Sequelize query:
|
||||||
Team.findAll({include: [City, Uniform]})
|
Team.findAll({include: [City, Uniform]})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For models that have a many-to-many relationship, you can also pass the plural version of the association.
|
||||||
|
```js
|
||||||
|
// returns all teams with their related City and Uniform models
|
||||||
|
// GET /teams?include=players
|
||||||
|
|
||||||
|
// results in a Sequelize query:
|
||||||
|
Team.findAll({include: [Player]})
|
||||||
|
```
|
||||||
|
|
||||||
## `limit` and `offset` queries
|
## `limit` and `offset` queries
|
||||||
Restricting list (`GET`) and scope queries to a restricted count can be done by passing `limit=<number>` and/or `offset=<number>`.
|
Restricting list (`GET`) and scope queries to a restricted count can be done by passing `limit=<number>` and/or `offset=<number>`.
|
||||||
|
|
||||||
|
10
src/crud.js
10
src/crud.js
@ -55,7 +55,15 @@ models: {
|
|||||||
export default (server, model, { prefix, defaultConfig: config, models: permissions }) => {
|
export default (server, model, { prefix, defaultConfig: config, models: permissions }) => {
|
||||||
const modelName = model._singular;
|
const modelName = model._singular;
|
||||||
const modelAttributes = Object.keys(model.attributes);
|
const modelAttributes = Object.keys(model.attributes);
|
||||||
const modelAssociations = Object.keys(model.associations);
|
const associatedModelNames = Object.keys(model.associations);
|
||||||
|
const modelAssociations = [
|
||||||
|
...associatedModelNames,
|
||||||
|
..._.flatMap(associatedModelNames, (associationName) => {
|
||||||
|
const { target } = model.associations[associationName];
|
||||||
|
const { _singular, _plural, _Singular, _Plural } = target;
|
||||||
|
return [_singular, _plural, _Singular, _Plural];
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
const attributeValidation = modelAttributes.reduce((params, attribute) => {
|
const attributeValidation = modelAttributes.reduce((params, attribute) => {
|
||||||
params[attribute] = joi.any();
|
params[attribute] = joi.any();
|
||||||
|
@ -32,6 +32,8 @@ const register = (server, options = {}, next) => {
|
|||||||
const { plural, singular } = model.options.name;
|
const { plural, singular } = model.options.name;
|
||||||
model._plural = plural.toLowerCase();
|
model._plural = plural.toLowerCase();
|
||||||
model._singular = singular.toLowerCase();
|
model._singular = singular.toLowerCase();
|
||||||
|
model._Plural = plural;
|
||||||
|
model._Singular = singular;
|
||||||
|
|
||||||
// Join tables
|
// Join tables
|
||||||
if (model.options.name.singular !== model.name) continue;
|
if (model.options.name.singular !== model.name) continue;
|
||||||
|
@ -20,6 +20,13 @@ export const parseInclude = request => {
|
|||||||
const { models } = noGetDb ? request : request.getDb();
|
const { models } = noGetDb ? request : request.getDb();
|
||||||
|
|
||||||
return include.map(a => {
|
return include.map(a => {
|
||||||
|
const singluarOrPluralMatch = Object.keys(models).find((modelName) => {
|
||||||
|
const { _singular, _plural } = models[modelName];
|
||||||
|
return _singular === a || _plural === a;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (singluarOrPluralMatch) return models[singluarOrPluralMatch];
|
||||||
|
|
||||||
if (typeof a === 'string') return models[a];
|
if (typeof a === 'string') return models[a];
|
||||||
|
|
||||||
if (a && typeof a.model === 'string' && a.model.length) {
|
if (a && typeof a.model === 'string' && a.model.length) {
|
||||||
|
Loading…
Reference in New Issue
Block a user