Skip to content
This repository
Newer
Older
100644 314 lines (217 sloc) 16.106 kb
3f957e40 »
2012-03-07 Add Gemnasium status
1 # RocketPants! [![Build Status](https://secure.travis-ci.org/filtersquad/rocket_pants.png?branch=master)](http://travis-ci.org/filtersquad/rocket_pants) [![Dependency Status](https://gemnasium.com/filtersquad/rocket_pants.png)](https://gemnasium.com/filtersquad/rocket_pants)
2
8f55fce1 »
2011-01-27 Add a skeleton readme
3
22b6142f »
2012-03-07 More readme tweaks.
4 ## Introduction
5
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
6 First thing's first, you're probably asking yourself - "Why the ridiculous name?". It's simple, really - RocketPants is memorable, and sounds completely bad ass. - everything a library needs.
98d2351c »
2012-03-05 README work and License tweaks
7
5e788d86 »
2012-03-06 Fixed typo in README
8 At its core, RocketPants is a set of tools (built around existing toolsets such as ActionPack) to make it easier to build well-designed APIs in Ruby and more importantly, along side Rails. You can think of it like [Grape](https://github.com/intridea/grape), a fantastic library which RocketPants was originally inspired by but with deeper Rails and ActionPack integration.
98d2351c »
2012-03-05 README work and License tweaks
9
10 ## Key Features
11
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
12 Why use RocketPants over alternatives like Grape or normal Rails? The reasons we built it come down to a couple of simple things:
98d2351c »
2012-03-05 README work and License tweaks
13
14 1. **It's opinionated** (like Grape) - In this case, we dictate a certain JSON structure we've found nice to work with (after having worked with and investigated a large number of other apis), it makes it simple to add metadata along side requests and the like.
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
15 2. **Simple and Often Automatic Response Metadata** - RocketPants automatically takes care of sending metadata about paginated responses and arrays where possible. This means as a user, you only need to worry about writing `expose object_or_presenter` in your controller and RocketPants will do it's best to send as much information back to the user.
16 3. **Extended Error Support** - RocketPants has a built in framework to manage errors it knows how to handle (in the forms of mapping exceptions to a well defined JSON structure) as well as tools to make it simple to hook up to Airbrake and do things such as including an error identifier in the response.
17 4. **It's built on ActionPack** - One of the key differentiators to Grape is that RocketPants embraces ActionPack and uses the modular components included from Rails 3.0 onwards to provide things you're familiar with already such as filters.
18 5. **Semi-efficient Caching Support** - Thanks to a combination of Rails middleware and collection vs. resource distinctions, RocketPants makes it relatively easy to implement "Efficient Validation" (See [here](http://rtomayko.github.com/rack-cache/faq)). As a developer, this means you get even more benefits of http caching where possible, without the need to generate full requests when etags are present.
98d2351c »
2012-03-05 README work and License tweaks
19
22b6142f »
2012-03-07 More readme tweaks.
20 ## Examples
21
22 ### A full example application
74b45679 »
2012-03-06 Add link to example app (not yet there)
23
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
24 Learn better by reading code? There is also have an example app mixing models and api clients over at [Sutto/transperth-api](https://github.com/Sutto/transperth-api) that is built using RocketPants.
74b45679 »
2012-03-06 Add link to example app (not yet there)
25
22b6142f »
2012-03-07 More readme tweaks.
26 ### Example controllers
27
28 Say, for example, you want to implement a random number endpoint that lets the user get a single random number between 1 and 100
29 or a collection of 5 random numbers. The controller in this case would look like:
30
31 ```ruby
32 class RandomNumbersController < RocketPants::Base
33
34 def index
35 numbers = (1..10).map { rand(100) + 1 }
36 expose numbers
37 end
38
39 def show
40 number = rand(100) + 1
41 expose number
42 end
43
44 end
45 ```
46
47 And in the router we'd just use the normal REST-like routes in Rails:
48
49 ```ruby
50 resources :random_numbers, :only => [:index, :show]
51 ```
52
98d2351c »
2012-03-05 README work and License tweaks
53 ## General Structure
54
55 RocketPants builds upon the mixin-based approach to ActionController-based rails applications that Rails 3 made possible. Instead of including everything like Rails does in `ActionController::Base`, RocketPants only includes the bare minimum to make apis. In the near future, it may be modified to work with `ActionController::Base` for the purposes of better compatibility with other gems.
56
57 Out of the box, we use the following ActionController components:
58
59 * `ActionController::HideActions` - Lets you hide methods from actions.
60 * `ActionController::UrlFor` - `url_for` helpers / tweaks by Rails to make integration with routes work better.
61 * `ActionController::Redirecting` - Allows you to use `redirect_to`.
62 * `ActionController::ConditionalGet` - Adds support for Rails caching controls, e.g. `fresh_when` and `expires_in`.
63 * `ActionController::RackDelegation` - Lets you reset the session and set the response body.
64 * `ActionController::RecordIdentifier` - Gives `dom_class` and `dom_id` methods, used for polymorphic routing.
65 * `ActionController::MimeResponds` - Gives `respond_to` with mime type controls.
66 * `AbstractController::Callbacks` - Adds support for callbacks / filters.
67 * `ActionController::Rescue` - Lets you use `rescue_from`.
68
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
69 And added our own:
98d2351c »
2012-03-05 README work and License tweaks
70
71 * `RocketPants::UrlFor` - Automatically includes the current version when generating URLs from the controller.
72 * `RocketPants::Respondable` - The core of RocketPants, the code that handles converting objects to the different container types.
73 * `RocketPants::Versioning` - Allows versioning requirements on the controller to ensure it is only callable with a specific api version.
74 * `RocketPants::Instrumentation` - Adds Instrumentation notifications making it easy to use and hook into with Rails.
75 * `RocketPants::Caching` - Implements time-based caching for index actions and etag-based efficient validation for singular resources.
76 * `RocketPants::ErrorHandling` - Short hand to create errors as well as simplifications to catch and render a standardised error representation.
77 * `RocketPants::Rescuable` - Allows you to hook in to rescuing exceptions and to make it easy to post notifications to tools such as AirBrake.
78
79 To use RocketPants, instead of inheriting from `ActionController::Base`, just inherit from `RocketPants::Base`.
80
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
81 Likewise, in Rails applications RocketPants also adds `RocketPants::CacheMiddleware` before the controller endpoints to implement ["Efficient Validation"](http://rtomayko.github.com/rack-cache/faq).
98d2351c »
2012-03-05 README work and License tweaks
82
149db467 »
2012-03-06 More README docs / tweaks
83 ## Installing RocketPants
84
85 Installing RocketPants is a simple matter of adding:
86
87 gem 'rocket_pants', '~> 1.0'
88
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
89 To your `Gemfile` and running `bundle install`. Next, instead of inherited from `ActionController::Base`, simply inherit from `RocketPants::Base` instead. If you're working with an API-only application, I typically change this in `ApplicationController` and inherit from `ApplicationController` as usual. Otherwise, I generate a new `ApiController` base controller along side `ApplicationController` which instead inherits from `RocketPants::Base` and place all my logic there.
149db467 »
2012-03-06 More README docs / tweaks
90
91 ## Configuration
92
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
93 Setting up RocketPants in your rails application is pretty simple and requires a minimal amount of effort. Inside your environment configuration, RocketPants offers the following options to control how it's configured (and their expanded alternatives):
149db467 »
2012-03-06 More README docs / tweaks
94
95 - `config.rocket_pants.use_caching` - Defaulting to true for production environments and false elsewhere, defines whether RocketPants caching setup as described below is used.
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
96 - `config.rocket_pants.cache` - A `Moneta::Store` instance used as the RocketPants cache, defaulting to a moneta memory instance. Change for proper caching. (See [here](https://github.com/wycats/moneta) for more information on Moneta.)
149db467 »
2012-03-06 More README docs / tweaks
97
98 ## Version Controllers / Routes
99
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
100 The current preferred way of dealing with version APIs in RocketPants is to do it using routes in the form of `/:version/:endpoint` - e.g. `GET /1/users/324`. RocketPants has support in the router and controller level for enforcing and controlling this. In the controller, it's a matter of specifying the required API versions:
149db467 »
2012-03-06 More README docs / tweaks
101
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
102 ```ruby
103 class UsersController < RocketPants::Base
104 version 1 # A single version
105 # or...
106 version 2..3 # 2-3 support this controller
107 end
108 ```
149db467 »
2012-03-06 More README docs / tweaks
109
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
110 And in the case of multiple versions, I strongly encourage namespaces the controllers inside modules. If the version param (as specified) by the URL does not match, then the specified controller will return an `:invalid_version` error as shown below.
149db467 »
2012-03-06 More README docs / tweaks
111
112 Next, in your `config/routes.rb` file, you can also declare versions using the following syntax and it will automatically set up the routes for you:
113
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
114 ```ruby
115 api :version => 1 do
116 get 'x', :to => 'test#item'
117 end
118 ```
149db467 »
2012-03-06 More README docs / tweaks
119
120 Which will route `GET /1/x` to `TestController#item`.
121
122 Likewise, you can specify a route for multiple versions by:
123
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
124 ```ruby
125 api :versions => 1..3 do
126 get 'x', :to => 'test#item'
127 end
128 ```
149db467 »
2012-03-06 More README docs / tweaks
129
98d2351c »
2012-03-05 README work and License tweaks
130 ## Working with data
131
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
132 When using RocketPants, you write your controllers the same as how you would with normal ActionController, the only thing that changes is how you handle data. `head` and `redirect_to` still work exactly the same as in Rails, but instead of using `respond_with` and `render` you instead use RocketPant's `exposes` methods (and it's kind). Namely:
3f8d609a »
2012-03-05 More type conversion docs
133
134 - `expose` / `exposes` - The core of all type conversion, will check the type of data and automatically convert it to the correct time (for either a singular, collection or paginated resource).
135 - `paginated` - Render an object as a paginated collection of data.
136 - `collection` - Renders a collection of objects - e.g. an array of users.
137 - `resource` - Renders a single object.
138
139 Along side the above that wrap data, it also provides:
140
141 - `responds` - Renders JSON, normalizing the object first (unwrapped).
142 - `render_json` - Renders an object as JSON.
143
144 ### Singular Resources
145
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
146 Singular resources will be converted to JSON via `serializable_hash`, passing through any objects
3f8d609a »
2012-03-05 More type conversion docs
147 and then wrapped in an object as the `response` key:
148
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
149 ```json
150 {
151 "response": {
152 "your": "serialized-object"
153 }
154 }
155 ```
3f8d609a »
2012-03-05 More type conversion docs
156
157 ### Collections
158
159 Similar to singular resources, but also include extra data about the count of items.
160
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
161 ```json
162 {
163 "response": [{
164 "name": "object-one"
165 }, {
166 "name": "object-two"
167 }],
168 "count": 2
169 }
170 ```
3f8d609a »
2012-03-05 More type conversion docs
171
172 ### Paginated Collections
173
174 The final type, similar to paginated objects but it includes details about the paginated data:
175
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
176 ```json
177 {
178 "response": [
179 {"name": "object-one"},
180 {"name": "object-two"},
181 {"name": "object-three"},
182 {"name": "object-four"},
183 {"name": "object-five"}
184 ],
185 "count": 5,
186 "pagination": {
187 "previous": 1,
188 "next": 3,
189 "current": 2,
190 "per_page": 5,
1e498dc1 »
2012-03-06 Missing comma in paginated collections example
191 "count": 23,
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
192 "pages": 5
193 }
194 }
195 ```
98d2351c »
2012-03-05 README work and License tweaks
196
197 ## Registering / Dealing with Errors
198
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
199 One of the built in features of RocketPants is the ability to handle rescuing / controlling exceptions and more importantly to handle mapping exceptions to names, messages and error codes.
4da07ec1 »
2012-03-05 Started writing docs on the error handling
200
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
201 This comes in useful when you wish to automatically convert exceptions such as `ActiveRecord::RecordNotFound` to a structured bit of data in the response. Namely, it makes it trivial to generate objects that follow the JSON structure of:
4da07ec1 »
2012-03-05 Started writing docs on the error handling
202
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
203 ```json
204 {
205 "error": "standard_error_name",
206 "error_description": "A translated error message describing what happened."
207 }
208 ```
4da07ec1 »
2012-03-05 Started writing docs on the error handling
209
210 It also adds a facilities to make it easy to add extra information to the response.
211
212 RocketPants will also attempt to convert all errors in the controller, defaulting to the `"system"` exception name and message as the error description. We also provide a registry to allow throwing exception from their symbolic name like so:
213
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
214 ```ruby
215 error! :not_found
216 ```
4da07ec1 »
2012-03-05 Started writing docs on the error handling
217
218 In the controller.
219
220 Out of the box, the following exceptions come pre-registered and setup:
221
222 - `:throttled` - The user has hit an api throttled error.
223 - `:unauthenticated` - The user doesn't have valid authentication details.
224 - `:invalid_version` - An invalid API version was specified.
225 - `:not_implemented` - The specified endpoint is not yet implemented.
226 - `:not_found` - The given resource could not be found.
227
98d2351c »
2012-03-05 README work and License tweaks
228 ## Implementing Efficient Validation
229
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
230 One of the core design principles built into RocketPants is simple support for "Efficient Validation" as described in the [Rack::Cache FAQ](http://rtomayko.github.com/rack-cache/faq) - Namely, it adds simple support for object-level caching using etags with fast verification thanks to the `RocketPants::CacheMiddleware` cache middleware.
149db467 »
2012-03-06 More README docs / tweaks
231
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
232 To do this, it uses `RocketPants.cache`, by default any Moneta-based store, to keep a mapping of object -> current cache key. RocketPants will then generate the etag when caching is enabled in the controller for singular-responses, generating an etag that can be quickly validated.
149db467 »
2012-03-06 More README docs / tweaks
233
234 For example, you'd add the following to your model:
235
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
236 ```ruby
237 class User < ActiveRecord::Base
238 include RocketPants::Cacheable
239 end
240 ```
149db467 »
2012-03-06 More README docs / tweaks
241
242 And then in your controller, you'd have something like:
243
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
244 ```ruby
245 class UsersController < RocketPants::Base
149db467 »
2012-03-06 More README docs / tweaks
246
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
247 version 1
149db467 »
2012-03-06 More README docs / tweaks
248
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
249 # Time based, e.g. collections, will be cached for 5 minutes - whilst singular
250 # items e.g. show will use etag-based caching:
251 caches :show, :index, :caches_for => 5.minutes
149db467 »
2012-03-06 More README docs / tweaks
252
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
253 def index
254 expose User.all
255 end
149db467 »
2012-03-06 More README docs / tweaks
256
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
257 def show
258 expose User.find(params[:id])
259 end
149db467 »
2012-03-06 More README docs / tweaks
260
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
261 end
262 ```
149db467 »
2012-03-06 More README docs / tweaks
263
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
264 When the user hits the index endpoint, it will generate an expiry-based caching header that caches the result for up to 5 minutes. When the user instead hits the show endpoint, it will generate a special etag that contains and object identifier portion and an object cache key. Inside `RocketPants.cache`, we store the mapping and then inside `RocketPants::CacheMiddleware`, we simply check if the given cache key matches the specified object identifier. If it does, we return a not modified response otherwise we pass it through to controller - giving the advantage of efficient caching without having to hit the full database on every request.
98d2351c »
2012-03-05 README work and License tweaks
265
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
266 ## Using with RSpec
73b2f4e7 »
2011-01-29 Add misc. test helpers
267
98d2351c »
2012-03-05 README work and License tweaks
268 RocketPants includes a set of helpers to make testing controllers built on `RocketPants::Base` simpler.
269
19b8bc56 »
2012-03-05 RSpec integration docs
270 * `be_singular_resource` - Checks the response is a single resource - e.g. `response.should be_siingular_resource`.
271 * `be_collection_resource` - Checks the response is collection of resources - e.g. `response.should be_collection_resource`.
272 * `be_paginated_response` - Checks the response is paginated - e.g. `response.should be_paginated_response`.
273 * `be_api_error(type = any)` - Checks it returned an error for the specified exception (or check the response is an error without any argument) - e.g. `response.should be_api_error RocketPants::NotFound`.
274 * `have_exposed(data, options = {})` - Given an object and conversion options, lets you check the output exposed the same object. e.g: `response.should have_exposed user`
275
276 Likewise, it adds the following helper methods:
277
278 - `parsed_body` - A parsed-JSON representation of the response.
279 - `decoded_body` - A `Hashie::Mash` of the response body.
280
281 To set up the integration, in your `spec/spec_helper.rb` add:
282
45ed4af7 »
2012-03-06 Fixed some small typos and enhanced syntax highlighting in the README
283 ```ruby
284 config.include RocketPants::TestHelper, :type => :controller
285 config.include RocketPants::RSpecMatchers, :type => :controller
286 ```
19b8bc56 »
2012-03-05 RSpec integration docs
287
288 Inside the `RSpec.configure do |config|` block.
98d2351c »
2012-03-05 README work and License tweaks
289
8ced3cbc »
2012-03-06 Update README.md
290 ## Contributors
291
292 - [Darcy Laycock](https://github.com/Sutto) - Main developer, current maintainer.
293 - [Steve Webb](https://github.com/swebb) - Helped with original work at [The Frontier Group](https://github.com/thefrontiergroup), inc. original design.
294 - [Fred Wu](https://github.com/fredwu) - README fixes.
295 - [Levi Buzolic](https://github.com/levibuzolic) - README fixes.
296
98d2351c »
2012-03-05 README work and License tweaks
297 ## Contributing
298
299 We encourage all community contributions. Keeping this in mind, please follow these general guidelines when contributing:
300
301 * Fork the project
302 * Create a topic branch for what you’re working on (git checkout -b awesome_feature)
303 * Commit away, push that up (git push your\_remote awesome\_feature)
304 * Create a new GitHub Issue with the commit, asking for review. Alternatively, send a pull request with details of what you added.
305 * Once it’s accepted, if you want access to the core repository feel free to ask! Otherwise, you can continue to hack away in your own fork.
306
307 Other than that, our guidelines very closely match the GemCutter guidelines [here](http://wiki.github.com/qrush/gemcutter/contribution-guidelines).
308
309 (Thanks to [GemCutter](http://wiki.github.com/qrush/gemcutter/) for the contribution guide)
73b2f4e7 »
2011-01-29 Add misc. test helpers
310
98d2351c »
2012-03-05 README work and License tweaks
311 ## License
73b2f4e7 »
2011-01-29 Add misc. test helpers
312
22b6142f »
2012-03-07 More readme tweaks.
313 RocketPants is released under the MIT License (see the [license file](https://github.com/filtersquad/rocket_pants/blob/master/LICENSE)) and is copyright Filter Squad, 2012.
Something went wrong with that request. Please try again.