2010-01-16 71 views
1

我都是爲了更瘦的控制器,更胖的模型心態。Rails:清理醜陋的控制器

我想知道如何去:

  1. 你怎麼確定的事情,應該被移動到你的模型(假設你和我一樣,你偷懶,需要重構自己的控制器,因爲你只是推在那裏的代碼)

  2. 如何編寫和結構控制器中新元素的創建。 請參閱以下示例。

我有一個polymophic 「投票」 相對凌亂控制器。我已經清理起來相當不錯,但我想知道如果我能改善這個動作好一點:

def up 
vote = Vote.new 
vote.vote = true 
vote.voter = current_user  
vote.voteable = Recipe.find params[:id] 
vote.save 
end 

對我來說只是一個小丑,我可能應該只使用create,而不是新的,但我想知道如果我使用非標準操作(關於REST)在這裏駕駛着致命的路徑。

我正在把它切換到new現在。但我絕對想得到社區的觀點。

回答

2

關鍵是測試驅動開發。一旦你成爲一種習慣,95%的時間都會回答代碼放置位置的問題。這是爲什麼。

單元測試(Rails中的模型測試)是測試代碼最簡單的地方。模型方法應該是單元測試的「黑盒子」風格 - 這意味着你不關心方法內部的內容,只需要輸入X提供輸出Y.這也會導致你在你的模型中編寫更多更小的方法,而不是非常大的方法。測試越簡單,越好 - 而不僅僅是爲了測試。更簡單的方法更容易被其他代碼覆蓋,這是Ruby的一大優勢。

另一方面,控制器(功能)測試將會發現您更關心裏面裏面發生了什麼動作,因爲這些方法不是剪切和乾的輸入/輸出場景。數據庫調用發生,會話變量設置等。Shoulda是一個很棒的測試套件,可以爲您自動完成大量的工作。

最後,我的建議是看看你最喜歡的插件,看看他們是如何做的。如果您對測試更感興趣,我有一篇關於restful controller tests in Shoulda的文章可能會讓您開始。

+0

優秀的建議。 – 2010-01-17 05:02:32

1

在REST風格的控制器,特別是有很多的動作我有時會造成的before_filter加載對象:

before_filter :load_recipe, :only => %w(show edit update destroy up down) 

private 
def load_recipe 
    @recipe = Recipe.find(params[:id]) 
end 

在你的情況下,我可能會考慮將投票給用戶的模式,所以你會碰到這樣的:

def up 
    current_user.vote(@recipe) 
end 

然後在你的模型:

class User < ActiveRecord::Base 
    has_many :votes 

    def vote(object) 
    votes.create(:vote => true, :voteable => object) 
    end 
end 

的是因爲您可以輕鬆地單獨測試投票行爲,並且可以重新使用該投票,如果您還有其他地方可能希望啓用投票(如通過其他操作的隱式結果進行投票,通過API進行投票,投票等)。

+0

嗯,感謝問題是它需要保持多態現在。 – 2010-01-17 01:04:27

+0

我不知道你在做什麼。我寫的和你的一樣多形(即不完全是因爲配方是明確的)。我的方法沒有任何方法可以排除完整的多態性(並且在某些方面它更好地支持它)。 – gtd 2010-01-18 22:10:00