2011-05-31 102 views
1

我擁有屬於另外兩個對象產品和服務的Transactions對象(作爲購物車的一部分)。產品和服務都與事務嵌套,以創建URL/products/1/transactions/new和/ services/1/transactions/new等URL。而且,這些表單是使用form_for [@product,@transaction] do | f |創建的類型格式。注意:產品和服務在設計和功能上差別很大,因此無法將它們組合成STI類型的單個對象。Rails 3購物車設計問題

我的問題是:沒有STI有沒有更好的方法來做到這一點?而且,檢查控制器以確定要採取行動的對象類型的最佳方法是什麼?

IE的新動作:

if ??? 
    @product = Product.find(params[:product_id]) 
    @transaction = @product.transactions.build 
elsif ??? 
    @service = Service.find(params[:service_id]) 
    @transaction = @service.transactions.build 
end 

與此相關的,沒有人知道,討論Rails 3的購物車設計的任何教程?我在書中見過一些,但他們使用會話來存儲整個購物車對象,在我看來,這不是很安全。而且,其他人過於簡單化。

任何幫助將不勝感激!

回答

1

我想你在這裏有兩個基本的選項。

(1)創建兩個事務類型/模型:product_transactions和service_transactions。兩者都可以從通用事務模塊繼承。這種方法可以讓你忽略這個問題:「我正在處理哪種交易?」並側重於事務模塊中的常見實現細節。然後,您可以維護兩個更簡單的嵌套控制器,即/products/<id>/transactions/services/<id>/transactions,這些控制器不需要進行類型檢查。

(2)將類型檢查移入常用事務模型。這種方法假設交易和產品或服務之間的交互將通過交易模塊進行處理,因此,您不必知道您正在與哪個交互模塊進行交互。例如:

class Transaction 
    belongs_to :service 
    belongs_to :product 

    def parent 
    @parent ||= product || service 
    end 

    def call_some_action_on_parent 
    parent.some_action 
    end 
end 

你可以在你的控制器類似的東西:

@parent = params[:service_id].blank? ? Product.find(params[:product_id]) : Service.find(params[:service_id]) 
@transaction = @parent.transactions.build(params[:transaction]) 

你看中真的應該根據周圍的事務對象您的需求決定的選項。如果有很多自定義代碼取決於您是否與產品或服務進行交互,則應遵循第一種方法。如果代碼基本相同,則應採取第二種方法,並重點關注事務與其父對象(產品,服務或其他)之間的契約,並忽略對象類型。本質上,你只關心父對象是否響應特定的方法,而不是實際上是什麼類型的對象。作爲一般規則,儘可能避免類型檢查並關注responds_to?方法。

+0

謝謝你非常詳細的回答和解釋!這是一個很大的幫助! – Justin 2011-05-31 20:29:34

+0

我有一個後續問題。我把它放在我的控制器中(作爲一個before_filter函數):@parent = params [:product_id] .blank? ? Service.find(params [:service_id]):Product.find(params [:product_id])。但是,在創建操作(@transaction = @ parent.transactions.build(params [:transaction]))時,當嘗試爲Service創建新事務時,出現錯誤「無法找到沒有ID的服務」。你知道爲什麼會發生這種情況嗎? – Justin 2011-06-01 17:57:56

+0

記錄params [:service_id]的值,如果它爲零或空白,則表明您沒有傳遞service_id或product_id。確保路徑參數是正確的。 – 2011-06-01 18:07:21