triAGENS/ArangoDB — pull request #911 by pluma (2014-06-17 23:20:04+00:00)
Title: Foxx Controller dependency injection

With the new Foxx exports we have a dependency problem when Foxx apps try to use (via `Foxx.requireApp` or `manager.mountedApp`) exports from apps before those are loaded.

The primary use case of requiring exports from other apps are controllers. Wrapping every reference to a `requireApp` import in a function adds unsightly clutter to otherwise perfectly readable route handling logic.

This PR adds an `inject` method to controllers to tidy things up a bit. Compare:

before:

```js
function getUserStorage() {
return Foxx.requireApp('users').userStorage;
}

controller.get('/users', function(req, res) {
res.json(getUserStorage().list());
});
```

after:

```js
controller.inject({
users: function() {
return Foxx.requireApp('users').userStorage;
}
});

controller.get('/users', function(req, res) {
res.json(this.users.list());
});
```

If the injected dependency is a function, its return value will be injected into the route's context ("`this`"), otherwise the dependency will be injected verbatim (if you really want to inject a function verbatim, just wrap it in another function).

The dependency factories (i.e. dependencies that are functions) are guaranteed not to be invoked until a route handler would be called (this solves the "app depending on other app to be mounted and ready" problem). Further, all dependency factories will have been invoked before that route handler itself is called (in other words: `this` is guaranteed to have all injected dependencies ready for use).

Also, each dependency factory will only be called exactly once. For consecutive requests, the result value is re-used. **Note:** this could cause a race condition when two requests are served in two parallel threads at roughly the same time, calling the factory for each request seems wasteful but the proposed implementation is likely **not** thread-safe.