From 83eadf0929a2506541e34b4a6f73d46bfa2404d3 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Wed, 26 Oct 2016 10:57:54 -0700 Subject: [PATCH 1/3] Fix: don't build CRUD routes until ready Previously, we were building the crud routes before we had run through the association logic. This meant that routes could get created without a complete list of associations available to it. This is slightly less performant b/c we need to run through two loops, but ensures that the full association data is available to all routes. --- src/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 48ddb4c..709a747 100644 --- a/src/index.js +++ b/src/index.js @@ -36,7 +36,6 @@ const register = (server, options = {}, next) => { // Join tables if (model.options.name.singular !== model.name) continue; - crud(server, model, options); for (const key of Object.keys(model.associations)) { const association = model.associations[key]; @@ -92,6 +91,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(); }; -- 2.34.1 From 07176018b7b8999ef9d4cc921bb87ab7774bf7c2 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Wed, 26 Oct 2016 10:58:50 -0700 Subject: [PATCH 2/3] Fix(crud) include param can be a string or array --- src/crud.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crud.js b/src/crud.js index 7ac31fc..fa856c7 100644 --- a/src/crud.js +++ b/src/crud.js @@ -62,8 +62,9 @@ export default (server, model, { prefix, defaultConfig: config, models: permissi return params; }, {}); + const validAssociations = joi.string().valid(...modelAssociations); const associationValidation = { - include: joi.array().items(joi.string().valid(...modelAssociations)), + include: [joi.array().items(validAssociations), validAssociations], }; const scopes = Object.keys(model.options.scopes); -- 2.34.1 From bcb78610619e6ed2c5e95c1d0fb3680ed492ffd3 Mon Sep 17 00:00:00 2001 From: Joey Baker Date: Wed, 26 Oct 2016 11:19:36 -0700 Subject: [PATCH 3/3] 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. --- README.md | 13 +++++++++++-- src/crud.js | 10 +++++++++- src/index.js | 2 ++ src/utils.js | 7 +++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 53746bc..a5cfdcc 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Getting related models is easy, just use a query parameter `include`. ```js // returns all teams with their related City model -// GET /teams?include=City +// GET /teams?include=city // results in a Sequelize query: 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. ```js // 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: 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 Restricting list (`GET`) and scope queries to a restricted count can be done by passing `limit=` and/or `offset=`. diff --git a/src/crud.js b/src/crud.js index fa856c7..6a9211d 100644 --- a/src/crud.js +++ b/src/crud.js @@ -55,7 +55,15 @@ models: { export default (server, model, { prefix, defaultConfig: config, models: permissions }) => { const modelName = model._singular; 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) => { params[attribute] = joi.any(); diff --git a/src/index.js b/src/index.js index 709a747..7580a15 100644 --- a/src/index.js +++ b/src/index.js @@ -32,6 +32,8 @@ const register = (server, options = {}, next) => { const { plural, singular } = model.options.name; model._plural = plural.toLowerCase(); model._singular = singular.toLowerCase(); + model._Plural = plural; + model._Singular = singular; // Join tables if (model.options.name.singular !== model.name) continue; diff --git a/src/utils.js b/src/utils.js index 7ca006b..bc19051 100644 --- a/src/utils.js +++ b/src/utils.js @@ -20,6 +20,13 @@ export const parseInclude = request => { const { models } = noGetDb ? request : request.getDb(); 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 (a && typeof a.model === 'string' && a.model.length) { -- 2.34.1