Fix(crud) include param lookup now works w/plurals #26

Merged
joeybaker merged 3 commits from fix-include into master 2016-10-26 18:42:15 +00:00
4 changed files with 38 additions and 5 deletions

View File

@ -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>`.

View File

@ -55,15 +55,24 @@ 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();
return params; return params;
}, {}); }, {});
const validAssociations = joi.string().valid(...modelAssociations);
const associationValidation = { const associationValidation = {
include: joi.array().items(joi.string().valid(...modelAssociations)), include: [joi.array().items(validAssociations), validAssociations],
}; };
const scopes = Object.keys(model.options.scopes); const scopes = Object.keys(model.options.scopes);

View File

@ -32,11 +32,12 @@ 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;
crud(server, model, options);
for (const key of Object.keys(model.associations)) { for (const key of Object.keys(model.associations)) {
const association = model.associations[key]; const association = model.associations[key];
@ -92,6 +93,13 @@ const register = (server, options = {}, next) => {
} }
} }
// build the methods for each model now that we've defined all the
// associations
Object.keys(models).forEach((modelName) => {
const model = models[modelName];
crud(server, model, options);
});
next(); next();
}; };

View File

@ -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) {