...if only the REST of life were this easy
Simply include the Coast module in your controller and get these actions for free.
But wait... there's more.
- Lightweight - about 200 lines of code... you can grok it in 5 minutes by skimming lib/coast.rb
- Unobtrusive - no monkey patches
- Flexible - support for html, xml, and json formats
- Familiar - simple DSL for hooking into action callbacks
- Secure - implicit authorization with your favorite libs... such as CanCan
Quick-start for the lazy
Assume you have a simple app structure for beach bums.
Install the GEM.
$gem install coast
Tweak some files.
# config/routes.rb Beach::Application.routes.draw do resources :beach_bums end
# app/controllers/beach_bums_controller.rb class BeachBumsController < ApplicationController include Coast end
Congratulations... you now have a RESTful API for beach bums.
Coast uses a Sinatra like DSL to provide hooks into the action lifecycle.
The following hooks are supported for each action.
before- before any other action logic is performed... just like a Rails before_filter
respond_to- after authorization and db work but before rendering or redirecting
after- after all other action logic is performed... just like a Rails after_filter
How to use the callbacks
# app/controllers/beach_bums_controller.rb class BeachBumsController < ApplicationController include Coast before :show do # take control and load a 'beach_bum' instead of letting Coast do it for us @resourceful_item = BeachBum.find(params[:id]) # Coast will implicitly create an @beach_bum variable that references @resourceful_item # cool eh? end respond_to :show do # take control of rendering or redirecting instead of letting Coast do it for us render :text => "Out surfing." end after :show do # do some last minute housekeeping after every thing else is done Rails.logger.info "Hey brah... we just completed the show action." end end
Coast implicitly calls an authorize method prior to executing any action logic.
You have complete control over this method. Here's an example.
# app/controllers/beach_bums_controller.rb class BeachBumsController < ApplicationController include Coast set_authorize_method :authorize def authorize(action, data, request) # restrict all RESTful actions raise "Unauthorized" end rescue_from Exception do |ex| render :text => "Not Allowed", :status => 401 end end
Note the authorize method signature. The first arg is the action being performed. The second arg is the record(s) being operated on. The last arg is the request object.
While originally written to support CanCan, its pretty simple to take control and manage authorization yourself.
Coast comes with few tricks up its sleeve.
If your model and controller names deviate from Rails conventions, you can explicitly set the model like so.
# app/controllers/beach_bums_controller.rb class BeachBumsController < ApplicationController include Coast set_resourceful_model SurferDude end
You can conditionally prevent mutating behavior on the server by setting an instance variable like so. It's a little arcane, but that's on purpose.
# app/controllers/beach_bums_controller.rb class BeachBumsController < ApplicationController include Coast before :create do # prevent the user from actually creating a record @skip_db_create = true end before :update do # prevent the user from actually saving a record @skip_db_update = true end before :destroy do # prevent the user from actually destroying a record @skip_db_destroy = true end end
There are some interesting additions to MiniTest::Mock since I mock some of Rails to make testing fast & fun.
Poke around the test code and let me know what you think.
How to run the tests.
$rvm 1.9.3 $gem install bundler $bundle $rake test
Ahh... passing tests.
I'm looking for hand-outs, so please fork and submit pull requests. Bug fixes, features, whatever...
-- Brandon Hayes, April 10, 2012