spine/spine — pull request #481 by adambiggs (2013-07-05 19:40:41+00:00)
Title: Spine.Route Proposal: Match multiple routes / ability to nest stacks

In response to #140, #159, #312, #373, and #398

### The Problem
Currently, `Spine.Route` only executes callbacks for the first matching route it finds. Other matching routes defined later on will never respond.

This means only a single controller can ever listen to a route (without returning `false` from a route callback as described in #312 [undocumented], or resorting to [less flexible workarounds](http://codecoverage.nl/blog/2012/04/17/nesting-stacks-in-spine-dot-js/)).

The most common problem this presents is that `Spine.Stack` instances can't be nested.

### Proposed Solution
In this pull request, `Spine.Route` will execute callbacks for *all* matching routes, starting from the least-specific and moving to the most specific (reverse order they were defined, so that more specific controllers are activated last).

Then the `'change'` event is triggered with an array of matching routes as the first argument (instead of a single instance). Routes in the array are in the order they were called (same order they were originally defined).

### Example
```coffee
class MainStack extends Spine.Stack

controllers:
'dashboard': Dashboard
'photos': Photos

routes:
'/photos*glob': 'photos' # globs can now be used to activate parent controllers
'/': 'dashboard'

class Photos extends Spine.Stack

controllers:
'index': PhotoList
'view': ViewPhoto
'edit': EditPhoto

routes:
'/photos/:id/edit': EditPhoto
'/photos/:id': ViewPhoto
'/photos': PhotoList
```

Previously if the URL changed from `/` to `/photos/123/edit`, the `EditPhoto` controller would be activated, but the `Photos` stack wouldn't... So the user wouldn't see anything change.

With this PR, the `Photos` stack would be activated first (because the glob route is a match), followed by the `EditPhoto` controller, resulting in the expected behaviour.