1

Rails アプリには、ユーザーが支払うことができるイベントがいくつかあります。現在のユーザーに応じてイベント価格を変更できるようにする必要があります。

* モデル内の current_user へのアクセスに関するトピックがすでにたくさんあることは知っていますが、私が探しているものではありません。

私は次の2つのモデルを持っています(本当に単純化されています)。チェックアウトは、イベントに関連付けられたすべての支払いを管理しています (実際のアプリでは、イベントとのポリモーフィックな関連付けがあるため、別のモデルでそれが必要でした)。

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常にパラメーターとして渡す以外に別の解決策がありますか?

4

3 に答える 3

3

これは良い質問です。モデルで current_user にアクセスしないことについてのご意見をお待ちしております。

実際、Event モデルはさらに少ないことを考慮する必要があります。モデルの主な仕事は、データを保存し、それ自体に関連するデータを処理することです。価格設定は、イベント モデルの問題ではなく、ビジネス ロジックです。イベントには価格があります。それで全部です。もういや。

ほら、価格設定について考慮すべきことがたくさんあります。ユーザーがプレミアムかどうかだけではありません。ユーザーがアプリで生後 6 か月の場合、いくらかの割引はどうですか? アプリの誕生日にプロモーションはいかがですか?酔っ払ったからという理由だけで売り物はいかがですか?イベントモデルを使用してそれらを処理すると、これらすべてが非常に複雑になります。これらすべての機能が今は必要ない場合でも、拡張する余地を残しておくことをお勧めします。

では、価格設定ロジックはどこで検討する必要がありますか? どうやらコントローラも良い場所ではありません。サービスオブジェクトを試してみましょう。

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

良い?

于 2013-08-30T12:30:06.327 に答える
0

current_user を渡したくない場合は、チェックアウトとイベントを渡す必要があります。メソッドは単一のオブジェクトでのみ呼び出すことができます。いずれにせよ、別のオブジェクトを渡す必要があります。

于 2013-08-30T11:40:59.640 に答える