我在這種情況下做了些什麼改變了不少。目前的方法如下:
我根據訪問需求分開控制器。這爲我提供了一個明確的心智模型和一個檢查訪問控制(並測試它)的非常簡單的方法。
我甚至會將模型中的「自己的訪問」分隔成單獨的 控制器。我通常也會把控制器的名字放在一個單獨的命名空間中。
這種方法也使得使用標準restuful控制器如InheritedResources的實現變得非常容易。
請注意,如果 不同類型的訪問需要相同的功能,則可以重用許多視圖。
所以我有這樣的事情:
### 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)