2012-05-11 45 views
0

嚴格的REST支持者可能會說,如果您發現自己在非CRUD的控制器上定義動作,那麼您應該強烈考慮創建新資源並將您的操作定義爲新資源上的CRUD操作。觀察Rails中的RESTful路由並耦合資源模型和控制器的最佳實踐?

一個示例可能是更改模型狀態的操作 - 比如購買。在此示例中,您可以創建CompletePurchasesController並使用create操作將購買的狀態更新爲完成,而不是在PurchaseController上定義「完成」操作。

假設上述情況,您顯然不會直接將PurchaseState保存到數據庫。

我的問題是您何時將控制器與模型耦合?你什麼時候定義一個PurchaseState模型(不是持久的),以及什麼時候直接使用Purchase。

這是一個複雜性問題,以及您在控制器操作中與之交互的鬆散關聯模型的數量?

回答

0

「完成」是(現有)購買上的狀態轉換事件。我發現將此操作概念化爲虛擬資源上的創建而不是耦合到Purchase模型的控制器上的更新操作(實際上是PurchaseController本身)是違反直覺的。

我會爲這種狀態轉換定義單獨的類似更新的動作。我認爲這樣可以以最經濟的方式利用rails結構,包括模型初始化,視圖分派,路由選擇,訪問控制。讓我們假設你通過簡單地增加

# routes.rb 
resource :purchase do 
    put :complete, :on => :member 
end 

# purchase_controller.rb 
def complete 
    @purchase.complete! 
end 

# cancan ability (entry already there for basic crud) 
can :manage, Purchase, :user_id => user.id 

你已經完成實現整個UI(查看/模型邏輯除外)使用inherited_resources,康康舞。 在軌道中是多麼的酷。

如果您的典型用例是購買只通過狀態轉換進行更新,尤其是具有相同訪問權限和重定向視圖的用戶,那麼我甚至會使用帶有state_event屬性的PurchaseController更新操作。見

Can somebody give an active record example for pluginaweek - statemachine?

嚴格的REST派,咬我! :)

0

爲了更新購買狀態,您可能只需要一個PurchasesController更新操作,您可以在路徑文件中將其定義爲'put'或'patch'方法。

如果更新中發生的所有情況都改變了購買對象上的狀態字段,那麼您可以在更新操作中正確執行該操作。

如果圍繞某些狀態轉換存在一些業務邏輯,但最終只是更改該購買對象,則可能需要將其放入購買模型中。

如果其他表格還在更新中,或者您還在爲用戶排隊等待郵件,祝賀他們購買新產品,那麼我認爲您可以添加單獨的PurchaseComplete或PurchaseAbort模型/服務對象。當行動的邏輯更加複雜時,這些似乎最自然地發揮作用,並且/或者您對多個模型進行了更改,或者正在做其他事情。