Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get the cats of a ninja #43

Closed
IngAjVillalon opened this issue Dec 28, 2018 · 7 comments
Closed

get the cats of a ninja #43

IngAjVillalon opened this issue Dec 28, 2018 · 7 comments
Labels
discussion 🔥 question Further information is requested

Comments

@IngAjVillalon
Copy link

IngAjVillalon commented Dec 28, 2018

I'm submitting a...

[ ] Regression 
[ ] Bug report
[x] Feature request
[x] Documentation issue or request

Hello, I return my collection of ninjas with a get in /ninjas.
I add a new ninja with a post in /ninjas.
I consult and modify the data of a ninja in /ninjas/id.

The ninjas can have cats.
I wish I could consult the cats of a ninja with a get in:
/ninjas/id/cats
add a new cat to a ninja with a post in /ninjas/id/cats
I would also like to be able to consult and modify a ninja's cat in /ninjas/id/cats/id

It's possible?

I found this link that has something similar:
#17

but if I do what is exposed there, the post and get methods stops working in /ninjas

How can I make everything work?

And for example in the URL
/ninjas/12/cats/10

Get the data of the cat 10 and its owner (the ninja 12)

Congratulations and thanks for your excellent work!

@Radecom
Copy link

Radecom commented Dec 28, 2018

That's a good question, I'm looking for exactly the same.
In order to manage the relationships in Nestjs.
Does anyone know how to manage the relationships in NestJs?

@Crewnie
Copy link

Crewnie commented Dec 28, 2018

I am looking for the same.
Missing that documentation on both sides.
How are handled many to many relationship in NestJs?
And how is it represented in routes?

@desarrollotrimax
Copy link

Please friend @shekohex , you are the nesting expert for routes and modules.
Please guide us on how to make relationships between classes and how to nest the routes and modules of relationships.

@shekohex shekohex added question Further information is requested discussion 🔥 labels Dec 29, 2018
@shekohex
Copy link
Member

Hello All.
SPOILER ALERT ⚠️ : a long answer with a lot of explanations on the way 😂

First, to achieve that task one must understand how express router works (since nest uses express-like adapters under the hood).
the way it works is so simple, so i will try to introduce it in a simple examples and in our context only, since we are discussing how to nest routes, i will talk about it a little bit:

the notion of examples will be HTTP_METHOD /routeControllerClass@routerHandler

so in our ninja and cats example we have:

  • GET /ninjaNinjaController@sayHello
  • GET /ninja/catsCatsController@sayHello

and what we need something like this:

  • GET /ninjaNinjaController@sayHello
  • GET /ninja/allNinjaController@getAllNinja
  • GET /ninja/:ninjaIdNinjaController@getNinjaById
  • GET /ninja/nested/catsCatsController@sayHello
  • GET /ninja/:ninjaId/catsCatsController@sayHello
  • GET /ninja/:ninjaId/cats/allCatsController@getAllCats
  • GET /ninja/:ninjaId/cats/:catIdCatsController@getCatById
    ...
  • POST /ninja/createNinjaController@createNinja
  • POST /ninja/:ninjaId/cats/createCatsController@createCat

note the order of the above routes, you will know the reason next 😃

that's an easy task with nest & nest router

first, take this as a role of thump, Always put your static routes before the dynamic one, by static and dynamic here i mean, the route is static if it dose not have any params in it, eg: /ninja/all and it is said to be dynamic if it would have dynamic params as in /ninja/:ninjaId.
That's how express works in first place, the route matching will first try to match the requested route by the order they appears in the code, let's assume for a moment that express somehow uses a Map<string, (req, res, next) ⇨ T>, and it calls Map#set whenever it sees a new route, so for example:

// the map keys.
// []
router.get('/ninja', ...); // ['ninja']
router.get('/ninja/cats', ...); // ['ninja', 'ninja/cats']
... // and so on.

the reason i told that you need to put your static routes before the dynamic is how express do it,
for example: the user requested /ninja/5 as defined as /ninja/:ninjaId then the ninjaId = 5, right ?
what if we have also added a /ninja/cats after that route ? Errors starts to happens, express will try to match the /ninja/:ninjaId instead of /ninja/cats/ and bind the ninjaId to cats, boom !

try this here: https://runkit.com/shekohex/express-routes101

so back to our issue, it's now easy how we could achieve this

here is a way to do it

// routes.ts
import { Routes } from 'nest-router';
import { CatsModule } from './cats/cats.module';
import { DogsModule } from './dogs/dogs.module';
import { NinjaModule } from './ninja/ninja.module';
export const routes: Routes = [
  {
    path: '/ninja',
    module: NinjaModule,
    children: [
      { path: 'nested/cats', module: CatsModule }, // note how i added that before the next route ?!
      { path: ':ninjaId/cats', module: CatsModule }, // wanna play ? try to reverse order this route with 1st one
      { path: '/dogs', module: DogsModule },
    ],
  },
];

now in your controllers, you can do what you want, but remember the role !
you can see/test/play with a full working example here: https://github.com/shekohex/nest-router/tree/master/examples/nest-v5x-m2m with all of the above routes implemented and tested.

@IngAjVillalon
Copy link
Author

Brother @shekohex , thank you very much for your explanation.
This has served me well enough to be able to continue on.
You are undoubtedly the master of routes and module nesting.
Congratulations bro!

@hzburki
Copy link

hzburki commented Sep 22, 2019

Let's say you add a route to get a ninja by Id. I assume this route does not need to be defined inside the routes file, rather we will just add another mothed with the @Get() decorator.

@Get(':id')
getNinjaById(@Param('id') id: number){
 // Some code here
}

The endpoint for this route would be;

API Endpoint: '/ninja/:id'

In this case, the path: '/dog' sub-route (child route) for ninja defined in the answer above will not be accessible.

The ninja/:id endpoint will always be evaluated before any of its children routes, therefore ninja/dog will also be evaluated as ninja/:id instead of ninja/dog.

I am facing this error. How should I go about fixing this?

@shekohex
Copy link
Member

Hi @hzburki, good question.
I came with a simple answer to it, since expressjs already support the regex named routes why not just using it here 😃!
Try this:
Instead of @Get(':id') do @Get('/:id(\\d+)/') assuming that the id is always numbers.
That way it would first try to match the id, if it's number then it will call this method normally, if not (as in case of ninja/dogs for example) it will fall through the next match which hopefully would be ninja/dogs.

Sorry I can't test this way at this moment, I'm using my mobile phone 📱

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion 🔥 question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants