2010-05-01 18 views
9

在我以前的學習項目中,我總是使用一個控制器,但現在我想知道這是否是一種好的做法,甚至總是可能的。應該通過不同的控制器來處理前端和後端嗎?

在所有RESTful Rails教程中,控制器都有showeditindex視圖。如果授權用戶已登錄,視圖變爲可用,並且index視圖顯示其他數據操縱控件,如刪除按鈕或指向edit視圖的鏈接。

現在我有一個Rails應用程序,它正好落在這個格局,但index的觀點是不能重複使用:

  1. 普通用戶看到有很多的圖片,複雜的佈局的浮華索引頁,沒有使用Javascript要求...
  2. 管理員用戶指數有完全地不同簡約設計,jQuery的表格和大量的附加數據,...

現在,我不知道如何處理這種情況。我可以想到以下內容:

  1. 單控制器,單視圖:視圖使用if語句分成兩個大塊/部分。
  2. 單控制器,兩個視圖:indexindex_admin
  3. 兩種不同的控制器:BookControllerBookAdminController

這些解決方案似乎完美的,但現在我傾向於使用第三個選項。

這樣做的首選方法是什麼?

回答

15

幾乎每次我收到一個新項目時,都會問自己這個問題。我通常選擇兩種解決方案之一:

1)。單控制器,單視圖

我幾乎從來沒有選擇這個解決方案,現在除非項目真的很簡單,只有一兩種類型的用戶。如果您獲得多種用戶類型,最好使用解決方案#2。儘管此解決方案可能很吸引人,因爲您認爲通過編寫較少的代碼可以節省一些時間,但最終,控制器和視圖的複雜性會增加。更不用說所有的邊緣情況,你必須考慮。這通常意味着錯誤。

我的公司曾經搶救過一個失敗的項目,它有3個用戶類型。(管理員,業務和成員)。他們使用瞭解決方案#1。代碼處於可怕的狀態,(這就是爲什麼我們被要求拯救這個項目)我們開玩笑說它不是MVC,而是MMM。 (模型 - 模型 - 模型)這是因爲業務邏輯沒有正確提取並放入模型中,而是在控制器和視圖中傳播。 2)。多個控制器,多個視圖

我現在越來越多地使用這個解決方案。我通常使用用戶類型命名空間控制器。例如:

在 「應用程序/控制器」

class BookController < ApplicationController 
end 

,並在 「應用程序/控制器/ admin」 的

class Admin::BookController < Admin::BaseController 
end 

我只需要考慮普通用戶,當我填寫BookController的,並當我填寫時,只需要考慮管理員用戶Admin::BookController

我不確定是否有更好的方法,但這是我從迄今爲止所做的十幾個項目中學到的...

2

使用兩個電流,如果有兩個模塊1管理員2]用戶

class BookUserController < ApplicationController 
    #Here layout is used will be of layouts/application.html.erb 
    #Here all the methods which user can will be present 
end 


class BookAdminController < ApplicationController 
    layout 'admin' #here we set the layout is layouts/admin.html.erb 

end 

只要你想展示管理員可以使用單個控制器和兩個方法之一頁

class BookUserController < ApplicationController 
    layout 'admin', :only=>['index_admin'] 

    def index_admin 


    end 

    def index 



    end 


end 

OR

class BookUserController < ApplicationController 
    def index_admin 

    render :action=>'index_admin', :layout => false 
    end 

    def index 



    end 


end 
3

我在這種情況下做了些什麼改變了不少。目前的方法如下:

我根據訪問需求分開控制器。這爲我提供了一個明確的心智模型和一個檢查訪問控制(並測試它)的非常簡單的方法。

我甚至會將模型中的「自己的訪問」分隔成單獨的 控制器。我通常也會把控制器的名字放在一個單獨的命名空間中。

這種方法也使得使用標準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) 
1

當我需要一個明確分開管理方面,我傾向於去有兩個控制器,用於一個資源的解決方案。管理界面的管理員/子目錄中有一個Admin :: BooksController,其中包含所有操作和一個只有索引和顯示方法的公共BooksController,具體取決於需求。