Separate out presentation logic from ContentItem.

Using one `as_json` method for presentation on both side of the
public/private divide meant we were only presenting publicly-visible
fields back in response to a `PUT` request, even if the errors we were
reporting were in private fields. Pulling these two views apart should
also make it easier to pull in titles and public-facing fields for
linked items.
Use the private presenter for the message queue.

As it stands, the view we send back to the publishing tool and the view
we send out to other publishing apps are the same; if this changes,
we'll need a third presenter.

The messages we send out need the `update_type` field; there's no harm
sending this back in responses to publishing tools, since they will have
provided it in the first place.
Add a `links` field to content items.

This includes validation on the shape and type of the `links` structure,
because Mongoid will only validate that the value is a hash: we need to
specify any further restrictions on the shape of that hash ourselves.
Add related links to the model.

This is intentionally over-simplified, to the point where it doesn't
take account of redirect items (or duplicate content IDs of any kind)
and is going to perform horribly on any decent-sized data set, but it
covers the basic idea.
Ignore redirects when looking up linked items.
Pick the latest content item with a content ID.

It is possible (for instance, when setting up a redirect) to have
multiple items with the same content ID. In these cases, the
latest-published wins.
Show linked items in the public content view.
Add API and web URLs to presented items.

This is in the simplest way that could possibly work, and doesn't yet
take advantage of Rails' path helpers to generate the API URLs.
Use Rails' helpers to generate API URLs.

Rails, given context from an application and a request, knows how to
generate the URL for a content item, but the presenter doesn't have
access to this logic. Passing this in as a callable to the presenter
gives us a very small interface to replicate in the tests, and lets us
keep the app's routing logic out of the presenter.

The app doesn't have any such context for the URLs as they're used on
the site, so there's no real benefit to pulling out the web URLs in the
same way.
Make linked item lookups index-covered.

By adding an index with the fields we want to query on, including the
fields we want to return and expose in the public presenter, we can make
it so the linked item query never has to load the document itself.

Once we have 100,000 items in the content store, rather than the 100 or
so we have at the moment, we'll need to take a closer look at this index
and how well it performs. For now, it turns a query that does a scan
over the entire collection into an index-covered query that should only
need to scan a single document.

As another performance consideration, we're currently doing a query for
each linked item; we'll need to revisit that as we incorporate more link
types and therefore more linked items.
Improve link validation error message assertions
Tighten up validation of links keys

This now requires that all keys in the links hash are underscored
alphanumeric strings.

This work also exposed a bug where nil would be allowed as a key.  This
is because when Enumerable#any? is used without a block, it returns true
if any of the items in the array are truthy.  This means that an array
containing nil returns false, so the validation was being skipped.