一种将客户从每周 1 次升级到 3 次再到 5 次的 DRYer 方法(即日期数学!)

A DRYer way to upgrade customer from 1 to 3 to 5 times a week (i.e., Date math!)

这是对人们来说非常明显的事情之一,但在代码方面我正在为如何编写它而苦苦挣扎。客户可以选择 3 个计划之一:

升级逻辑简化如下:

"every Monday already paid for"在代码中是一个数组array_of_mondays。从那里开始,我一团糟,我想不出如何擦干...

prices = {1=>15, 3=>12, 5=>10} 
array_of_mondays.each do |m|
  if current_plan == 1 && new_plan == 3
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(3, 0, m))
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
    Stripe::InvoiceItem.create(
      customer: self.user.stripe_customer_id,
      amount: (new_plan – current_plan) * prices[new_plan],
      currency: “usd”
    )
  elsif current_plan == 1 && new_plan == 5
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(2, 0, m))
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(3, 0, m))
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(4, 0, m))
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
    Stripe::InvoiceItem.create(
      customer: self.user.stripe_customer_id,
      amount: (new_plan – current_plan) * prices[new_plan],
      currency: “usd”
    )
  elsif current_plan == 3 && new_plan == 5
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(4, 0, m))
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
    Stripe::InvoiceItem.create(
      customer: self.user.stripe_customer_id,
      amount: (new_plan – current_plan) * prices[new_plan],
      currency: “usd”
    )
  end
end

我使用的方法 date_of_next_X_day_Y_days_out_from_Z_start 有助于确定实际日期:

def date_of_next_X_day_Y_days_out_from_Z_start(wday, number_of_days, start_date)
    number_of_days = number_of_days.to_i
    wday = wday.to_i
    day_ahead = start_date + number_of_days.days
    (day_ahead) + ((7 - day_ahead.wday + wday) % 7).days
    #returns Date object
end

换句话说,它正在做的是说创建一个 plan_dateddate 是下周二,从指定的周一(例如,下周二)开始 0 天

好吧,实际上我只是一时灵机一动,想到了一个可能的答案,但很想听听其他人的意见:

prices = {1=>15, 3=>12, 5=>10}
dates_to_be_created = { [1,3] => [3,5], [1,5] => [2,3,4,5], [3,5] => [4,5] }
array_of_mondays.each do |m|
  dates_to_be_created[[current_plan,new_plan]].each do |d|
    self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(d, 0, m))
  end
  Stripe::InvoiceItem.create(
    customer: self.user.stripe_customer_id,
    amount: (new_plan – current_plan) * prices[new_plan],
    currency: “usd”
  )
end