Today I decided to go ahead and convert UsersController
to a REST resource. There were two non-standard methods left (#edit_membership
and #destroy_membership
) but I can’t see a clear way to refactor them yet. So I just converted the controller to a resource and added those methods as member routes.
Before
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# config/routes.rb map.with_options :controller => 'users' do |users| users.with_options :conditions => {:method => :get} do |user_views| user_views.connect 'users', :action => 'index' user_views.connect 'users/:id', :action => 'show', :id => /\d+/ user_views.connect 'users/new', :action => 'new' user_views.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil end users.with_options :conditions => {:method => :post} do |user_actions| user_actions.connect 'users/new', :action => 'create' user_actions.connect 'users/:id/memberships', :action => 'edit_membership' user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership' user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership' end users.connect 'users/:id/edit', :action => 'update', :conditions => {:method => :put} end |
After
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# config/routes.rb map.with_options :controller => 'users' do |users| users.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil, :conditions => {:method => :get} users.with_options :conditions => {:method => :post} do |user_actions| user_actions.connect 'users/:id/memberships', :action => 'edit_membership' user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership' user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership' end end map.resources :users, :member => { :edit_membership => :post, :destroy_membership => :post }, :except => [:destroy] |
This conversion wasn’t as clean as I would have hoped but it will be good enough for now. The problems are:
- The
#edit
action needs routes to each of it’s tabs so they can be linked to directly. -
#edit_membership
and#destroy_membership
each have their own custom route underneath Users. Normally these could be refactored to a nested route but… - Redmine already has a
MembersController
that is used for similar actions as#edit_membership
and#destroy_membership
. The big difference is thatUsersController
is an administrator controller whileMembersController
is a project manager controller. This means there will need to be a bunch of refactoring to merge them.
At the very least, UsersController
now has some pretty clear public actions now. Adding a REST API to it should be a lot easier now.