In my previous learning projects I always used a single controller, but now I wonder if that is good practice or even always possible.
In all RESTful Rails tutorials the
What I do in such a situation changed quite a bit lately. The current approach is as follows:
I separate controllers based on access requirements. This gives me a clear mental model and a very easy way to check for access control (and test it).
I even go as far as to separate 'your own access' to models into separate controller. I also usually keep the controller's name just put it into a separate namespace.
This approach is also makes it very easy to use standard restuful controller implementations like InheritedResources.
Note that you can reuse many of the views if same functionality is required for different kinds of access.
So I'd have something like this:
### lets start with routes
# this is basically guest access level. you can only list it and see details
map.resources :books, :only => [:index, :show]
namespace :my do |my|
# this will require at least login.
# index and show will be basically same as at the guest level. we can reuse the views
my.resources :books
end
namespace :admin do |admin|
# this will require admin login
admin.resources :books
end
# now the controllers
# this might be just enough of a controller code :). the rest goes into model.
class BooksController < InheritedResources::Base
actions :index, :show
end
module My
class BooksController < InheritedResources::Base
before_filter :require_user
protected
def begin_of_association_chain
# this will force resources to be found on current_user.books.
# so if you go to /my/books/123 and book 123 is not your book you will get 404
current_user
end
end
end
module Admin
class BooksController < InheritedResources::Base
before_filter :require_admin
# this controller is essentially unrestricted. you can get/edit/update any book
# and you can have separate view template for index too
end
end
## Views
# well, this is the part that I like the least in this approach, but
# I think the good outweight the bad.
# I see 2 ways to reuse the views w/o writing lots of ugly customization code for the InheritedResources
# 1) render 'parent' views inside templates. i.e. like:
# my/books/index.html.haml:
!= render :file => "/books/index"
# or just link the templates on the filesystem level with symlinks.
# (or if all of them are the same you can link the directory)