Framework

Facilitates mapping URLs to controller actions based on a user-defined configuration file. It is responsible for observing and acting upon URL changes. It does no direct action apart from notifiying the dispatcher of such a change however.

Routes

By convention, routes should be declared in a separate module (typically routes.coffee). For example:

match'likes/:id','likes#show'

match('likes/:id','likes#show');

This works much like the Ruby on Rails counterpart. If a route matches, a router:match event is published passing a params hash which contains pattern matches (like id in the example above) and additional GET parameters parsed from the query string. This hands control over to the Dispatcher.

Between the router and the controllers, there is the Dispatcher listening for routing events. On such events, it loads the target controller, creates an instance of it and calls the target action. The action is actually a method of the controller. The previously active controller is automatically disposed.

The mediator is an event broker that implements the Publish/Subscribe design pattern. It should be used for most of the inter-module communication in Chaplin applications. Modules can emit events using this.publishEvent in order to notify other modules, and listen for such events using this.subscribeEvent. The mediator can also be used to easily share data between several modules, like a user model or other persistent and globally accessible data.

A controller is the place where a model and associated views are instantiated. Typically, a controller represents one screen of the application. There can be one current controller which provides the main view and represents the current URL.

By convention, there is a controller for each application module. A controller may provide several action methods like index, show, edit and so on. These actions are called by the Dispatcher when a route matches.

Maps to a collection to generate a list of item views that are bound to the models in the collection.

Flow

Every Chaplin application starts with a class that inherits from Application. This is merely a bootstrapper which instantiates and configures the four core modules: Dispatcher, Layout, mediator, and Router (in that order).

After creating the Router, the routes are registered. Usually they are read from a configuration file called routes.{coffee,js}. A route maps a URL pattern to a controller action. For example, the path / can be mapped to the index action of the HomeController.

After the Application invokes startRouting; the Router starts to observe the current URL. If a route matches, it notifies the other modules.

This is where the Dispatcher takes over. It loads the target controller and its dependencies (e.g. HomeController). Then, the controller is instantiated and the controller action is called (e.g. index). An action is a method of the controller. The Dispatcher also keeps track of the currently active controller, and disposes the previously active controller.

Typically, a controller creates a Model or Collection and a corresponding View. The model or collection may fetch some data from the server which is then rendered by the view. By convention, the models, collection and views are saved as properties on the controller instance.

A core concern of the Chaplin architecture is proper memory management. While there isn’t a broad discussion about garbage collection in JavaScript applications, it is an important topic, especially in single-page applications, where the lifetime and multitude of objects increases compared to earlier architectures. In event-driven systems, registering events creates references between objects. If these references aren’t removed when a module is no longer in use, the garbage collector can’t free the memory.

Since Backbone provides little out of the box to manage memory, Chaplin extends Backbone’s Model, Collection and View classes to implement a powerful disposal process which ensures that each controller, model, collection and view cleans up after itself.