README.md in restfulness-0.1.0 vs README.md in restfulness-0.2.0
- old
+ new
@@ -25,11 +25,11 @@
get :public_timeline do
Status.limit(20)
end
desc "Return a personal timeline."
- get :home_timeline do
+ get :home_timeline do
authenticate!
current_user.statuses.limit(20)
end
desc "Return a status."
@@ -126,12 +126,10 @@
"/" => MyRailsApp::Application,
"/api" => MyAppAPI.new
)
```
-By default, Restfulness comes with a Rack compatible dispatcher, but in the future it might make sense to add others.
-
If you want to run Restfulness standalone, simply create a `config.ru` that will load up your application:
```ruby
require 'my_app'
run MyApp.new
@@ -141,11 +139,11 @@
```
bundle exec rackup
```
-For an example, checkout the `/example` directory in the source code.
+For a very simple example project, checkout the `/example` directory in the source code.
### Routes
The aim of routes in Restfulness are to be stupid simple. These are the basic rules:
@@ -177,10 +175,11 @@
Resources are like Controllers in a Rails project. They handle the basic HTTP actions using methods that match the same name as the action. The result of an action is serialized into a JSON object automatically. The actions supported by a resource are:
* `get`
* `head`
* `post`
+ * `patch`
* `put`
* `delete`
* `options` - this is the only action provded by default
When creating your resource, simply define the methods you'd like to use and ensure each has a result:
@@ -190,12 +189,12 @@
# Return the basic object
def get
project
end
- # Update the object
- def put
+ # Update the existing object with some new attributes
+ def patch
project.update(params)
end
protected
@@ -288,15 +287,103 @@
# Request params
request.params # {'key' => 'value'} - usually a JSON deserialized object
```
+## Error Handling
+
+If you want your application to return anything other than a 200 (or 202) status, you have a couple of options that allow you to send codes back to the client.
+
+The easiest method is probably just to update the `response` code. Take the following example where we set a 403 response and the model's errors object in the payload:
+
+```ruby
+class ProjectResource < Restfulness::Resource
+ def patch
+ if project.update_attributes(request.params)
+ project
+ else
+ response.status = 403
+ project.errors
+ end
+ end
+end
+```
+
+The favourite method in Restfulness however is to use the `HTTPException` class and helper methods that will raise the error for you. For example:
+
+```ruby
+class ProjectResource < Restfulness::Resource
+ def patch
+ unless project.update_attributes(request.params)
+ forbidden!(project.errors)
+ end
+ project
+ end
+end
+```
+
+The `forbidden!` bang method will call the `error!` method, which in turn will raise an `HTTPException` with the appropriate status code. Exceptions are permitted to include a payload also, so you could override the `error!` method if you wished with code that will automatically re-format the payload. Another example:
+
+```ruby
+# Regular resource
+class ProjectResource < ApplicationResource
+ def patch
+ unless project.update_attributes(request.params)
+ forbidden!(project) # only send the project object!
+ end
+ project
+ end
+end
+
+# Main Application Resource
+class ApplicationResource < Restfulness::Resource
+ # Overwrite the regular error handler so we can provide
+ # our own format.
+ def error!(status, payload = "", opts = {})
+ case payload
+ when ActiveRecord::Base # or your favourite ORM
+ payload = {
+ :errors => payload.errors.full_messages
+ }
+ end
+ super(status, payload, opts)
+ end
+end
+
+```
+
+This can be a really nice way to mold your errors into a standard format. All HTTP exceptions generated inside resources will pass through `error!`, even those that a triggered by a callback. It gives a great way to provide your own more complete result, or even just resort to a simple string.
+
+The currently built in error methods are:
+
+ * `not_modified!`
+ * `bad_request!`
+ * `unauthorized!`
+ * `payment_required!`
+ * `forbidden!`
+ * `resource_not_found!`
+ * `request_timeout!`
+ * `conflict!`
+ * `gone!`
+ * `unprocessable_entity!`
+
+If you'd like to see me more, please send us a pull request! Failing that, you can create your own by writing something along the lines of:
+
+```ruby
+def im_a_teapot!(payload = "")
+ error!(418, payload)
+end
+```
+
+
## Caveats and TODOs
Restfulness is still very much a work in progress. Here is a list of things that we'd like to improve or fix:
- * Support for more serializers, not just JSON.
+ * Support for more serializers and content types, not just JSON.
+ * Support path methods for automatic URL generation.
+ * Support redirect exceptions.
* Reloading is a PITA (see note below).
* Needs more functional testing.
* Support for before and after filters in resources, although I'm slightly aprehensive about this.
## Reloading
@@ -332,9 +419,13 @@
Restfulness was created by Sam Lown <me@samlown.com> as a solution for building simple APIs at [Cabify](http://www.cabify.com).
## History
+
+### 0.2.0 - October 17, 2013
+
+Refactoring error handling and reporting so that it is easier to use and simpler.
### 0.1.0 - October 16, 2013
First release!