kieran / barista

A URL router / generator for NodeJS
https://kieran.github.io/barista/
MIT License
111 stars 22 forks source link

Getting url from .url method by route_name #8

Closed denchistyakov closed 11 years ago

denchistyakov commented 11 years ago

Good day, Kieran, I use you library and find it very pretty and usefull, but every time I had one problem with URL generation — if I had several rules witch dispatching to one action I can`nt generate correct URL for them. For example:

router.get('/download/')
      .to('download.index')
      .name('download');

router.get('/download/:os/')
      .to('download.index')
      .name('download_os');

router.get('/download/:os/:type/')
      .to('download.index')
      .name('download_os_type');

And if I pass in template:

router.url({
    controller: 'download',
    action: 'index',
    os: 'win'
})

I get "/download/" instead of "/download/win/", because rules for "/download/" defined above (

Maybe you add possibility to send string with route_name to .url method equally with pair controller + action?

kieran commented 11 years ago

Hey Denis,

The router will give you back the URL for the _first_ route that satisfies your conditions. The quickest fix would be to just define your routes in the reverse order:

router.get('/download/:os/:type/') //... would return if there are both :os and :type
router.get('/download/:os/') //... would return if there is :os
router.get('/download/') //... will always match

Since they all resolve to the same endpoint, you could also define them as one route with optional segments:

router.get('/download(/:os)(/:type)') //... would match & generate all 3 routes above

Since barista doesn't yet support nested optional segments, you'll want to use a where() clause to specify what's valid for either the :os or :type variables:

router.get('/download(/:os)(/:type)')
      .to('download.index')
      .where({
        os: [ 'win', 'mac', 'linux' ] // :os must match one of these values
      })

Let me know if any of those don't work fo you!

denchistyakov commented 11 years ago

Hey Kieran, that`s me again, Tnx for you detailed answer. I am trying direct and reverse order before ask you, but in reverse order I got absolutely opposite problem.

router.get('/download/:os/:type/').to('download.index');
router.get('/download/:os/').to('download.index');
router.get('/download/').to('download.index');

router.url({ controller: 'download', action: 'index' });             // /download/// — not OK
router.url({ controller: 'download', action: 'index', os: 'win' });  // /download/win// — not OK

You variant with router.get('/download(/:os)(/:type)') almost fine, instead of case

router.url({ controller: 'download', action: 'index', type: 'full' });     // /download/full/

because „(/:os)“ part not obligatory, and we get invalid url (