Rails: DRY controllers with ResourceController

Rail's generated RESTful controllers are great for quickly building up an interface to your models, but I quickly grew tired of writing the same code for simply managing resources through REST. This was compounded once I started using Rspec to test my controllers, and found myself writing endless virtually identical tests. So, inspired by some reading, I set about DRYing up all this boilerplate code and built a ResourceController class.

ResourceController extends the normal ActionController, but provides a series of hooks for fetching, creating, updating and deleting resources. By default, these hook methods are called automatically by the default REST actions (index, show, new, create, edit, update, and destroy). This means creating a standard controller is as simple as:

class ApplesController < ResourceController

end```


The hook methods are protected, so their default functionality can be overridden:


fetch_resources - called before index

fetch_resource - called before show, edit, update, destroy

create_resource - called before new

save_resource - called by create, update

destroy_resource - called by delete


ResourceController infers the name of the resource it is managing from the name of the subclass, so an ApplesController will manage Apple models. Where appropriate, the name will be pluralized, so in this example, the index action will automatically generate an instance variable array called @apples.


The code comes with RSpec controller examples.


**Caveats**

Currently, ResourceController cannot handle resources that are nested.


**Installation and Use**

Assuming a new Rails project with a users model:

bashrails demo

cd demo

script/generate rspec

script/generate model user emailaddress:string passwordhash:string password_salt:string active:boolean

rake db:migrate```

ResourceController depends on RESTful routes, so add an entry to your config/routes.rb:

# ...

map.resources :users

# ...```


Next, in your project folder, generate a controller in the normal way

bashscript/generate rspec_controller users index show new create edit update destroy```

Modify the generated controller to extend ResourceController:

class UsersController < ResourceController

  # Remove any generated stub methods

end```


Copy the ResourceController files into your project:

bashcp resourcecontroller.rb {apppath}/lib/

cp resourcecontrollerspec.rb {app_path}/spec/controllers/```

Next, modify the UsersController's spec file, removing RSpec's auto-generated examples:

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

require File.expand_path(File.dirname(__FILE__) + '/resource_controller_spec') # Be sure to add this line

describe UsersController do

  it_should_behave_like "a resource controller"

end```


You can now check that the controller works as expected by running:

bashrake spec:controllers```

Please feel free to make use of and modify this code as you wish; if you do improve it, please leave a comment below or email me and I'll update here. I'll also post the code on either Launchpad or github. I'm preferring bazaar's simplicity to git at the moment.

Resources

resource_controller.tar.gz

resourcecontrollerdemo.tar.gz