Add request state updating functionality to API

WIP

Adds a new `update_state` method to the API that uses the existing API key mechanism to send a status update to a request created via an external API request. Intended usage - foi-register end-users confirming whether the information they requested has been disclosed ([the parallel work on foi-register can be found here](https://github.com/mysociety/foi-register/tree/issues/169-ask-user-to-confirm-request-state)). Status description mismatches should be handled on the foi-register side but unexpected status values are rejected with a 500 error by the API.

Adds an optional parameter to the pre-existing `add_correspondence` API method to allow it to update status (intended use - updates from a public body) if a `state` value is supplied. Again, the foi-register code is responsible for handling state description mismatches but in this case the API deals with erroneous data by ignoring that part of the request.

Apologies for having restructured `api_controller_spec` but I kept losing track of which API methods the various tests were targeting. I will be happy to change it back before finalising the Pull Request if I've caused trouble.
This message was created automatically by mail delivery software.

A message that you sent could not be delivered to one or more of its
recipients. This is a temporary error. The following address(es) deferred:

  skenaja@gmail.com
    Domain alexskene.com has exceeded the max emails per hour (405/400 (101%)) allowed.  Message will be reattempted later

------- This is a copy of the message, including all the headers. ------
Received: from github-smtp2-ext6.iad.github.net ([192.30.252.197]:37204 helo=github-smtp2b-ext-cp1-prd.iad.github.net)
	by zurich.footholds.net with esmtps (UNKNOWN:DHE-RSA-AES256-GCM-SHA384:256)
	(Exim 4.82)
	(envelope-from <noreply@github.com>)
	id 1WzpXr-0008Ta-UB
	for alex@alexskene.com; Wed, 25 Jun 2014 16:55:36 +0100
Date: Wed, 25 Jun 2014 08:55:25 -0700
From: Hound <notifications@github.com>
Reply-To: mysociety/alaveteli <reply@reply.github.com>
To: mysociety/alaveteli <alaveteli@noreply.github.com>
Message-ID: <mysociety/alaveteli/pull/1631/r14195032@github.com>
In-Reply-To: <mysociety/alaveteli/pull/1631@github.com>
References: <mysociety/alaveteli/pull/1631@github.com>
Subject: Re: [alaveteli] Add request state updating functionality to API
 (#1631)
Mime-Version: 1.0
Content-Type: multipart/alternative;
 boundary="--==_mimepart_53aaf0ed4588f_56d63f977b85b2c0138924";
 charset=UTF-8
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Recipient: skenaja
List-ID: mysociety/alaveteli <alaveteli.mysociety.github.com>
List-Archive: https://github.com/mysociety/alaveteli
List-Post: <mailto:reply@reply.github.com>
List-Unsubscribe: <mailto:unsub+p-14195032-43971b11775f7c6c3c4477f120d232e7961e7299-510285@reply.github.com>,
 <https://github.com/notifications/unsubscribe/510285__eyJzY29wZSI6Ik5ld3NpZXM6TXV0ZSIsImV4cGlyZXMiOjE3MTkzMzA5MjUsImRhdGEiOnsiaWQiOjM1MzExOTc0fX0=--1b82db7ce017b4b86bed02ec0d5ba2449dbec4c5>
X-Auto-Response-Suppress: All
X-GitHub-Recipient-Address: alex@alexskene.com


----==_mimepart_53aaf0ed4588f_56d63f977b85b2c0138924
Content-Type: text/plain;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

>  
> -        InfoRequest.count(:conditions => [
> -            "public_body_id = ?",
> -            public_bodies(:geraldine_public_body).id]
> -        ).should == number_of_requests + 1
> +        it 'should raise a JSON 403 error if an invalid state is supplied' do
> +            # First we need an external request
> +            request_id = info_requests(:external_request).id
> +
> +            # Initially it has no incoming messages
> +            IncomingMessage.count(:conditions => ["info_request_id = ?", request_id]).should == 0
> +
> +            # Now add one
> +            sent_at = "2012-05-28T12:35:39+01:00"
> +            response_body = "Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n"

Line is too long. [323/80]

---
Reply to this email directly or view it on GitHub:
https://github.com/mysociety/alaveteli/pull/1631/files#r14195032
----==_mimepart_53aaf0ed4588f_56d63f977b85b2c0138924
Content-Type: text/html;
 charset=UTF-8
Content-Transfer-Encoding: 7bit

<p>In spec/controllers/api_controller_spec.rb:</p>
<pre style='color:#555'>&gt;  
&gt; -        InfoRequest.count(:conditions =&gt; [
&gt; -            &quot;public_body_id = ?&quot;,
&gt; -            public_bodies(:geraldine_public_body).id]
&gt; -        ).should == number_of_requests + 1
&gt; +        it &#39;should raise a JSON 403 error if an invalid state is supplied&#39; do
&gt; +            # First we need an external request
&gt; +            request_id = info_requests(:external_request).id
&gt; +
&gt; +            # Initially it has no incoming messages
&gt; +            IncomingMessage.count(:conditions =&gt; [&quot;info_request_id = ?&quot;, request_id]).should == 0
&gt; +
&gt; +            # Now add one
&gt; +            sent_at = &quot;2012-05-28T12:35:39+01:00&quot;
&gt; +            response_body = &quot;Thank you for your request for information, which we are handling in accordance with the Freedom of Information Act 2000. You will receive a response within 20 working days or before the next full moon, whichever is sooner.\n\nYours sincerely,\nJohn Gandermulch,\nExample Council FOI Officer\n&quot;
</pre>
<p>Line is too long. [323/80]</p>

<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">&mdash;<br>Reply to this email directly or <a href="https://github.com/mysociety/alaveteli/pull/1631/files#r14195032">view it on GitHub</a>.<img alt="" height="1" src="https://github.com/notifications/beacon/510285__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcxOTMzMDkyNSwiZGF0YSI6eyJpZCI6MzUzMTE5NzR9fQ==--4983e8c2a2a0b6873a3d3494fc7dc344661b39e7.gif" width="1" /></p>
----==_mimepart_53aaf0ed4588f_56d63f977b85b2c0138924--