[英]Rails: Cleaning up ugly controllers
我全力支持更瘦的控制器,更胖的模型思維方式。
我想知道如何去做:
如何確定應移至模型的事物(假設您像我一樣,並且變得懶惰,並且需要重構控制器,因為您只是在其中推入了代碼)
您如何在控制器中編寫和組織新元素的創建。 請參見以下示例。
例
我有一個相對混亂的控制器,用於多詞“表決”。 我已經很好地清理了它,但是我想知道是否可以更好地改進此操作:
def up
vote = Vote.new
vote.vote = true
vote.voter = current_user
vote.voteable = Recipe.find params[:id]
vote.save
end
對我來說,這有點丑陋,我可能應該只使用create
而不是new,但是我想知道我是否正在通過使用非標准操作(關於REST)來推動這條致命的道路。
我正在努力將其切換為new
。 但是我絕對想了解社區的觀點。
關鍵是測試驅動開發。 一旦養成習慣,就會在95%的時間為您回答在哪里放置代碼的問題。 這就是為什么。
單元測試(Rails中的模型測試)是測試代碼最容易的地方。 模型方法應該經過單元測試的“黑匣子”樣式-意味着您不在乎方法內部是什么,只不過輸入X提供了輸出Y。這也將導致您在模型中編寫大量較小的方法,而不是非常大的方法。 測試越容易,就越好-而且不僅僅是為了測試。 更簡單的方法更易於被其他代碼覆蓋,這是Ruby的一大優勢。
另一方面,控制器(功能)測試將使您更關心動作內部發生的事情,因為這些方法並不是多余的,而且不會浪費輸入/輸出場景。 發生數據庫調用,設置會話變量,等等。Shoulda是一個很棒的測試套件,可以自動為您執行很多操作。
最后,我的建議是查看一些您喜歡的插件,以了解它們的運行情況。 而且,如果您對測試有更多的興趣,我會在《 Shoulda》上發表有關靜態控制器測試的文章,這可能會讓您入門。
在RESTful控制器中,尤其是通過大量操作,有時我會創建一個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投票,大量投票一樣) -投票等)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.