Skip to content
This repository
Newer
Older
100644 274 lines (191 sloc) 14.812 kb
8f55fce1 »
2011-01-27 Add a skeleton readme
1 # Rocket Pants!
2
98d2351c »
2012-03-05 README work and License tweaks
3 First thing's first, you're probably asking yourself - "Why the ridiculous name?". It's simple, really - Rocket Pants is memorable, and sounds completely bad ass. Everything a library needs.
4
5 At it's core, Rails is a set of tools (built around existing toolsets such as ActionPack) to make it easier to build well-designed API's 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 original inspired by but with deeper Rails and ActionPack integration.
6
7 ## Key Features
8
9 Why use Rocket Pants over alternatives like Grape or normal Rails? The reasons we built it come down to a couple of
10 simple things:
11
12 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.
136a5858 »
2012-03-05 Remove irrelevant sections
13 2. **Simple and Often Automatic Response Metadata** - Rocket Pants 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 Rocket Pants will do it's best to send as much information back to the user.
98d2351c »
2012-03-05 README work and License tweaks
14 3. **Extended Error Support** - Rocket Pants has a build 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.
15 4. **It's build on ActionPack** - One of the key differentiators to Graphe is that Rocket Pants embraces ActionPack and uses the modular components included from Rails 3.0 onwards to provide things you're familiar with already such as filters.
16 5. **Semi-efficient Caching Support** - Thanks to a combination of Rails middleware and collection vs. resource distinctions, Rocket Pants makes it relatively easy to implement "Efficient Validation" (See 'http://rtomayko.github.com/rack-cache/faq' [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
17 etags are present.
18
19 ## General Structure
20
21 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.
22
23 Out of the box, we use the following ActionController components:
24
25 * `ActionController::HideActions` - Lets you hide methods from actions.
26 * `ActionController::UrlFor` - `url_for` helpers / tweaks by Rails to make integration with routes work better.
27 * `ActionController::Redirecting` - Allows you to use `redirect_to`.
28 * `ActionController::ConditionalGet` - Adds support for Rails caching controls, e.g. `fresh_when` and `expires_in`.
29 * `ActionController::RackDelegation` - Lets you reset the session and set the response body.
30 * `ActionController::RecordIdentifier` - Gives `dom_class` and `dom_id` methods, used for polymorphic routing.
31 * `ActionController::MimeResponds` - Gives `respond_to` with mime type controls.
32 * `AbstractController::Callbacks` - Adds support for callbacks / filters.
33 * `ActionController::Rescue` - Lets you use `rescue_from`.
34
35 And add our own:
36
37 * `RocketPants::UrlFor` - Automatically includes the current version when generating URLs from the controller.
38 * `RocketPants::Respondable` - The core of RocketPants, the code that handles converting objects to the different container types.
39 * `RocketPants::Versioning` - Allows versioning requirements on the controller to ensure it is only callable with a specific api version.
40 * `RocketPants::Instrumentation` - Adds Instrumentation notifications making it easy to use and hook into with Rails.
41 * `RocketPants::Caching` - Implements time-based caching for index actions and etag-based efficient validation for singular resources.
42 * `RocketPants::ErrorHandling` - Short hand to create errors as well as simplifications to catch and render a standardised error representation.
43 * `RocketPants::Rescuable` - Allows you to hook in to rescuing exceptions and to make it easy to post notifications to tools such as AirBrake.
44
45 To use RocketPants, instead of inheriting from `ActionController::Base`, just inherit from `RocketPants::Base`.
46
47 Likewise, in Rails applications RocketPants also adds `RocketPants::CacheMiddleware` before the controller endpoints to implement
48 ["Efficient Validation"](http://rtomayko.github.com/rack-cache/faq).
49
149db467 »
2012-03-06 More README docs / tweaks
50 ## Installing RocketPants
51
52 Installing RocketPants is a simple matter of adding:
53
54 gem 'rocket_pants', '~> 1.0'
55
56 To your `Gemfile` and running `bundle install`. Next, instead of inherited from `ActionController::Base`, simply
57 inherit from `RocketPants::Base` instead. If you're working with an API-only application, I typically change this
58 in `ApplicationController` and inherit from `ApplicationController` as usual. Otherwise, I generate a new `ApiController`
59 base controller along side `ApplicationController` which instead inherits from `RocketPants::Base` and place all my logic
60 there.
61
62 ## Configuration
63
64 Setting up RocketPants in your rails application is pretty simple and requires a minimal amount of effort. Inside your environment configuration, RocketPants offers the
65 following options to control how it's configured (and their expanded alternatives):
66
67 - `config.rocket_pants.use_caching` - Defaulting to true for production environments and false elsewhere, defines whether RocketPants caching setup as described below is used.
68 - `config.rocket_pants.cache` - A `Moneta::Store` instance used as the rocket pants cache, defaulting to a moneta memory instance. Change for proper caching. (See [here](https://github.com/wycats/moneta) for more information on Moneta.)
69
70 ## Version Controllers / Routes
71
72 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`.
73 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:
74
75 class UsersController < RocketPants::Base
76 version 1 # A single version
77 # or...
78 version 2..3 # 2-3 support this controller
79 end
80
81 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
82 controllre will return an `:invalid_version` error as shown below.
83
84 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:
85
86 api :version => 1 do
87 get 'x', :to => 'test#item'
88 end
89
90 Which will route `GET /1/x` to `TestController#item`.
91
92 Likewise, you can specify a route for multiple versions by:
93
94 api :versions => 1..3 do
95 get 'x', :to => 'test#item'
96 end
97
98d2351c »
2012-03-05 README work and License tweaks
98 ## Working with data
99
3f8d609a »
2012-03-05 More type conversion docs
100 When using RocketPants, you write your controllers the same as how you would with normal ActionController, the only thing that
101 changes is how yoy handle data. `head` and `redirect_to` still work exactly the same as in Rails, but instead of using `respond_with` and
102 `render` you instead use RocketPant's `exposes` methods (and it's kind). Namely:
103
104 - `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).
105 - `paginated` - Render an object as a paginated collection of data.
106 - `collection` - Renders a collection of objects - e.g. an array of users.
107 - `resource` - Renders a single object.
108
109 Along side the above that wrap data, it also provides:
110
111 - `responds` - Renders JSON, normalizing the object first (unwrapped).
112 - `render_json` - Renders an object as JSON.
113
114 ### Singular Resources
115
116 Singular resources will be converted to json via `serializable_hash`, passing through any objects
117 and then wrapped in an object as the `response` key:
118
119 {
120 "response": {
121 "your": "serialized-object"
122 }
123 }
124
125 ### Collections
126
127 Similar to singular resources, but also include extra data about the count of items.
128
129 {
130 "response": [{
131 "name": "object-one"
132 }, {
133 "name": "object-two"
134 }],
135 "count": 2
136 }
137
138 ### Paginated Collections
139
140 The final type, similar to paginated objects but it includes details about the paginated data:
141
142 {
143 "response": [
144 {"name": "object-one"},
145 {"name": "object-two"},
146 {"name": "object-three"},
147 {"name": "object-four"},
148 {"name": "object-five"}
149 ],
150 "count": 5,
151 "pagination": {
152 "previous": 1,
153 "next": 3,
154 "current": 2,
155 "per_page": 5,
156 "count": 23
157 "pages": 5
158 }
159 }
98d2351c »
2012-03-05 README work and License tweaks
160
161 ## Registering / Dealing with Errors
162
4da07ec1 »
2012-03-05 Started writing docs on the error handling
163 One of the built in features of rocketpants is the ability to handle rescuing / controlling exceptions and more importantly to handle mapping
164 exceptions to names, messages and error codes.
165
166 This comes in useful when you wish to automatically convert exceptions such as `ActiveRecord::RecordNotFound` to a structured bit of data in
167 the response. Namely, it makes it trivial to generate objects that follow the JSON structure of:
168
169 {
170 "error": "standard_error_name",
171 "error_description": "A translated error message describing what happened."
172 }
173
174 It also adds a facilities to make it easy to add extra information to the response.
175
176 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:
177
178 error! :not_found
179
180 In the controller.
181
182 Out of the box, the following exceptions come pre-registered and setup:
183
184 - `:throttled` - The user has hit an api throttled error.
185 - `:unauthenticated` - The user doesn't have valid authentication details.
186 - `:invalid_version` - An invalid API version was specified.
187 - `:not_implemented` - The specified endpoint is not yet implemented.
188 - `:not_found` - The given resource could not be found.
189
98d2351c »
2012-03-05 README work and License tweaks
190 ## Implementing Efficient Validation
191
149db467 »
2012-03-06 More README docs / tweaks
192 One of the core design principles built into RocketPants is simple support for "Efficient Validation" as described in the
193 [Rack::Cache FAQ](http://rtomayko.github.com/rack-cache/faq) - Namely, it adds simple support for object-level caching using
194 etags with fast verification thanks to the `RocketPants::CacheMiddleware` cache middleware.
195
196 To do this, it uses `RocketPants.cache`, by default any Moneta-based store, to keep a mapping of object -> current cache key.
197 Rocket Pants will then generate the etag when caching is enabled in the controller for singular-responses, generating an etag that can be quickly validated.
198
199 For example, you'd add the following to your model:
200
201 class User < ActiveRecord::Base
202 include RocketPants::Cacheable
203 end
204
205 And then in your controller, you'd have something like:
206
207 class UsersController < RocketPants::Base
208
209 version 1
210
211 # Time based, e.g. collections, will be cached for 5 minutes - whilst singular
212 # items e.g. show will use etag-based caching:
213 caches :show, :index, :caches_for => 5.minutes
214
215 def index
216 expose User.all
217 end
218
219 def show
220 expose User.find(params[:id])
221 end
222
223 end
224
225 When the user hits the index endpoint, it will generate an expiry-based caching header that caches the result for up to 5 minutes.
226 When the user instead hits the show endpoint, it will generate a special etag that contains and object identifier portion and an
227 object cache key. Inside `RocketPants.cache`, we store the mapping and then inside `RocketPants::CacheMiddleware`, we simply check
228 if the given cache key matches the specified object identifier. If it does, we return a not modified response otherwise we pass
229 it through to controller - giving the advantage of efficent caching without having to hit the full database on every request.
98d2351c »
2012-03-05 README work and License tweaks
230
231 ## An Example Controller / App
232
233 TODO: Link to the transperth client here.
73b2f4e7 »
2011-01-29 Add misc. test helpers
234
235 ## Using with Rspec
236
98d2351c »
2012-03-05 README work and License tweaks
237 RocketPants includes a set of helpers to make testing controllers built on `RocketPants::Base` simpler.
238
19b8bc56 »
2012-03-05 RSpec integration docs
239 * `be_singular_resource` - Checks the response is a single resource - e.g. `response.should be_siingular_resource`.
240 * `be_collection_resource` - Checks the response is collection of resources - e.g. `response.should be_collection_resource`.
241 * `be_paginated_response` - Checks the response is paginated - e.g. `response.should be_paginated_response`.
242 * `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`.
243 * `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`
244
245 Likewise, it adds the following helper methods:
246
247 - `parsed_body` - A parsed-JSON representation of the response.
248 - `decoded_body` - A `Hashie::Mash` of the response body.
249
250 To set up the integration, in your `spec/spec_helper.rb` add:
251
252 config.include RocketPants::TestHelper, :type => :controller
253 cconfig.include RocketPants::RSpecMatchers, :type => :controller
254
255 Inside the `RSpec.configure do |config|` block.
98d2351c »
2012-03-05 README work and License tweaks
256
257 ## Contributing
258
259 We encourage all community contributions. Keeping this in mind, please follow these general guidelines when contributing:
260
261 * Fork the project
262 * Create a topic branch for what you’re working on (git checkout -b awesome_feature)
263 * Commit away, push that up (git push your\_remote awesome\_feature)
264 * Create a new GitHub Issue with the commit, asking for review. Alternatively, send a pull request with details of what you added.
265 * 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.
266
267 Other than that, our guidelines very closely match the GemCutter guidelines [here](http://wiki.github.com/qrush/gemcutter/contribution-guidelines).
268
269 (Thanks to [GemCutter](http://wiki.github.com/qrush/gemcutter/) for the contribution guide)
73b2f4e7 »
2011-01-29 Add misc. test helpers
270
98d2351c »
2012-03-05 README work and License tweaks
271 ## License
73b2f4e7 »
2011-01-29 Add misc. test helpers
272
98d2351c »
2012-03-05 README work and License tweaks
273 API Smith is released under the MIT License (see the [license file](LICENSE)) and is
274 copyright Filter Squad, 2012.
Something went wrong with that request. Please try again.