2013-08-30 40 views
1

在我的rails應用程序中,我有一些用戶可以支付的事件。我需要能夠根據當前用戶更改事件價格。取決於rails中的current_user的模型方法

*我知道已經有很多關於模型訪問CURRENT_USER話題,但它不是我要找的。*

我有2個以下車型(真正簡單)。 Checkout管理與事件相關的所有支付事件(我需要在一個單獨的模型中使用它,因爲它與事件中的多態關聯在真實應用程序中)。

class Event < ActiveRecord::Base 
    attr_accessible :ticket_price, :checkout 
    has_one :checkout 

    checkout_price 
    # Here I'd like to be able to use the current_user to change price accordingly 
    # Example: user.premium? ? ticket_price/2 : ticket_price 
    ticket_price 
    end 
end 

class Checkout < ActiveRecord::Base 
    attr_accessible :event 
    belongs_to :event 

    def total 
    event.checkout_price 
    end 

    def free? 
    total == 0 
    end 
end 

我能明顯界定checkout_price(user)但我要通過它的每一個地方(例如event.checkout_price(current_user)checkout.total(current_user)checkout.free?(current_user))。

我知道從模型中訪問current_user是個不好的習慣(而且我絕對不想這樣做),但是在我的情況下,有沒有比作爲參數始終傳遞current_user作爲參數的另一種解決方案?

回答

2

這是一個很好的問題,我非常感謝您對不訪問model中current_user的意見。

事實上,事件模型應該考慮更少。模型的主要工作是存儲數據並處理與其自身相關的數據。定價是您的業務邏輯,而不是事件模型的關注點。一個事件有一個價格。就這樣。不再。

看,你有很多事情要考慮定價。不僅如果用戶是溢價或不。如果用戶在您的應用中使用6個月,那麼折扣如何?如何在應用程序的生日提升?僅僅因爲你喝醉了而怎麼樣呢?如果你使用Event模型來處理它們,那麼所有這些將會非常複雜。即使你現在不需要所有這些功能,最好留出一些空間來擴展。

那麼在哪裏應該考慮定價邏輯?顯然,控制器也不是一個好地方。讓我們嘗試服務對象。

class PricingService 

    def initialize(event, user) 
    @user = user 
    @event = event 
    @price = event.price 
    end 

    def get_price 
    # The place for your easily adding rules. Or use some meta programming. 
    # say go through all instance methods starting with "pricing_" 
    pricing_premium_user 
    pricing_app_birthday 
    pricing_old_event 
    @price 
    end 

    def pricing_premium_user 
    @price -= 10 if user.premium? 
    end 

    def pricing_app_birthday 
    @price = @price*0.9 if Time.current.today == APP_BIRTHDAY 
    end 

    def pricing_old_event 
    @price = @price*0.9 if event.created_at < (Time.current - 1.week) 
    end 

end 

然後在控制器

# Checkout 
def new 
    @event = method_to_find_event 
    pricing = PricingService.new(@event, current_user) 
    @event.price = pricing.get_price 
    # blah blah 
end 

尼斯使用它呢?

+0

謝謝,我必須適應它,但它看起來非常好! (特別是'醉酒折扣';))。 – TimPetricola

+0

@TimPetricola,我的榮幸:)您可以通過Google服務對象獲取更多信息。 –

0

如果你不想通過current_user那麼你必須通過結賬&事件。方法只能在單個對象上調用。無論哪種方式,你必須傳遞另一個對象。

1

將用戶設置爲關聯或實例變量比在多個不同對象上的多個位置上傳遞它更好。在您考慮它時,每個結帳都屬於該用戶,不是嗎?

就像是:

class Checkout < ActiveRecord::Base 
    attr_accessible :event 
    belongs_to :event 
    belongs_to :user 

    def total 
    event.checkout_price(user) 
    end 

    def free? 
    total == 0 
    end 
end 

你一定要確保你創建出記錄時設置的用戶。

+0

實際上,每個事件只有一個'Checkout',Checkout模型通過'Charge'模型鏈接到'User'模型。但是我不能依賴這個,因爲只有當用戶付款時,我才使用我的方法(例如,只是不顯示事件與相應的價格) – TimPetricola

+0

Ahm,這看起來有點反直覺 - 也許這將有助於,如果你會解釋你的領域模型(類)多一點,否則它是太抽象建議一些......可能值得考慮重構Checkout和Charge模型到Checkout中,當用戶收費時它會改變狀態(收費);你可以在用戶會話中保存checkout_id。但再次,很難說,因爲我不知道初始模型或完整域模型的原因... – jurglic

+0

感謝您的幫助。我非常喜歡Billy Chan提出的服務方式,我認爲這種情況確實很有意義。 – TimPetricola

相關問題