A Picture is Worth 1000 Lies

August 4, 2014

Last week, I wrote about Routing in EmberJS. And I kinda lied a bit. I laid out the Pokédex route like this …

App.router.map(function(){
this.route(“pokedex”, {path: ‘/pokedex/:poke_id’});
});

That’s probably the wrong choice, but I made it for Pedagogical reasons. I regret nothing, but we are going to play with the routes of an example application to think through some design decisions and pick up a small detail of the router I overlooked. Resources.

A Picture is worth 1000 words

I’m a Father, Husband, etc. That means we are generating Gigabytes of pictures. Some are even in focus. She’s two, and fast. So, we are going to build a photo sharing site! Let’s give it a classy name. I’m thinking Phlickr. Um, legal informs me that’s a bit too similar some other upstart.

Introducing PhotoAlbum

PhotoAlbum is the latest in picture sharing technology. Some of our neat features are:

  • Friends
  • Albums
  • Tags
  • Favorites
  • Popular Pictures
  • Searching
  • Dashboard

Laying the Groundwork

I’m going to start by giving some examples of pages and their Urls.

  • Index – ‘/’
  • Login – ‘/login’
  • Dashboard – ‘/dashboard’
  • Popular Pictures – ‘/popular’
  • My Friends – ‘/friends’
  • Search – ‘/search/’
  • Tags – ‘/tags/’
  • Tag – ‘/tag/Sunny%20Days’
  • My Page – ‘/U/Brian’
  • Viewing My Album – ‘/U/Brian/album/sketchnotes’
  • My Albums – ‘/U/Brian/albums’
  • Creating a new album – ‘/U/Brian/albums/new’
  • My Friends Albums – ‘/U/Matt/albums’
  • A Photo – ‘/U/Brian/photo/24153’
  • My Photos – ‘/U/Brian/photos’
  • Uploading a photo – ‘/U/Brian/photos/new’

Cartography in Code (Making a Map)

Router.map(function() { this.route(‘login’); this.route(‘dashboard’); this.route(‘popular’); this.route(‘friends’); this.route(‘search’); this.route(‘tags’); this.route(‘tag’, {path: ‘/tag/:tagname’}); this.resource(‘posters’, {path: ‘/U’}, function(){ this.resource(‘user’, {path: ‘/:username’}, function(){ this.route(‘album’, {path: ‘/album/:albumname’}); this.resource(‘albums’, function(){ this.route(‘new’); }); this.route(‘photo’, {path: ‘/photo/:photo_id’}); this.resource(‘photos’, function(){ this.route(‘new’); }); }); }); });

What’s the Difference?

Routes are for individual pages. Routes cannot be nested. If we want nested pages, we use resources. And resources give us a few new defaults.

Defaults

By default, the router gives us the route named ‘index’. And that in turn builds the controller, route, and loads the template named ‘index’. A resource is like a mini router in that way. If we name a resource ‘posters’, then all the child routes are prefixed with the name, including a new default ‘index’. The tetrad is listed out below. When deeply nested, only the resource and route matter for naming as opposed to the parent resources. Example, the template for the new albums is ‘albumsNew’ despite the albums resource being a child of the user resource.

  • RouteName – postersIndex
  • Controller – PostersIndexController
  • Route – PostersIndexRoute
  • template – postersIndex

Chains

The defaults are not the only things. They nest, just like applications. The posters resource looks for a template named ‘posters’ and then the child template. While I won’t dwell too much templates now, remember when the application template had an ‘{{outlet}}’? Well, the ‘posters’ template can have an ‘{{outlet}}’ as well. this allow the templates to nest.

But it’s not just the templates, the controllers nest as well. So the model and properties of a parent controller can be accessed by a child. And the routes nest. Each parent finishing before the child runs.

A Time to Choose

Of course we can use routes to describe everything here. I’m fairly sure. But we will have all kinds of issues with reuse. the nesting of controllers and routes gives us a sensible place to hang some code reuse. The really interesting thing is I chose my routes and resources strictly based on what Urls made sense, what parts belong to other pieces of information. For example, there is only one dashboard, yours. The login is also independent of other data. However, each photo album belongs to a user. Matt’s album Dinners I Made is totally different from my album Dinners I Made. And while a picture has a tag, the collection of tags is only useful when it belongs to the system as a whole, allowing me to find all the pictures tagged sunrise regardless of who posted it. Once again, it all comes down to following the Urls and letting them tell you all you need to know.

This post originally appeared at https://myotherpants.com/2014/08/a-picture-is-worth-1000-lies/