0

我希望创建一个类似于 Ticketmaster 上的购买计时器,在订单回滚之前,您有 x 分钟的时间支付订单。

不过,我不太确定该怎么做。在有人提出建议后查看了delayed_job gem和railscast,似乎功能有所不同——延迟作业允许您延迟一个动作,但不会使延迟以其他任何事情的发生为条件,我可以不知道该怎么做。

我基本上是在寻找可以让我

a)有(伪)代码有点像这样

if job_timer == 0
   @order.destroy
   #Some redirect/flash stuff
end

b) 在页面上显示该计时器(即,“在您的订单被撤销之前,您还有 3 分 25 秒的时间来支付。”)

有什么想法可以做什么/去哪里看?

谢谢,

萨沙

4

2 回答 2

3

Delayed_job 是您正在寻找的。

例如,您可以拥有一个遍历所有订单对象的函数。

def purge_orders
  # purge_at is an attribute of order that contains 
  # the datetime when the order should be deleted.
  Order.where("purge_at >= #{DateTime.current}").each {|order| order.destroy }
end

第二个问题更像是一个javascript问题。这个想法是,Rails 将剩余时间传递给客户端,然后 javascript 根据 Rails 端给出的剩余时间创建一个计时器。将 javascript 放入您的视图文件中。理想情况下,您应该在资产文件夹中隔离 javascript,但我不会在这里为您这样做。

<script language="JavaScript">
TargetDate = <%= @order.purge_at - DateTime.current %>;
BackColor = "palegreen";
ForeColor = "navy";
CountActive = true;
CountStepper = -1;
LeadingZero = true;
DisplayFormat = "%%D%% Days, %%H%% Hours, %%M%% Minutes, %%S%% Seconds.";
FinishMessage = "It is finally here!";
</script>
<script language="JavaScript" src="http://scripts.hashemian.com/js/countdown.js"></script>

原始 javascript 代码的来源

于 2012-10-15T20:46:42.243 回答
1

虽然delayed_job 可能可以处理这个问题,但它并不像前面的答案所暗示的那么简单。

我认为它看起来像这样:

订单.rb:

after_create :schedule_check_payment

def schedule_check_payment
  self.delay(:run_at => 5.minutes.from_now, :queue => :payment_checks).check_payment
end

def check_payment
  self.reload
  unless payment_exists #check if the user has paid
    self.destroy
  end
end

我也可以想到对这种技术的一些警告:

  1. 一旦延迟的作业工作者在 5 分钟后空闲,检查就会运行,但如果队列得到备份,则可能需要更长时间。这就是为什么我为延迟处理指定一个队列。我相信您可以设置 delay_job 以便它的一个(或多个)工作人员只会处理该队列中的作业。这样,如果您将来开始将延迟作业用于其他较慢的任务(并且您可能会,它是一个非常方便的宝石),它们不太可能通过消耗所有延迟的处理资源来拖累您的付款支票。

  2. 延迟作业序列化调用延迟方法的对象。如果有关订单本身的某些内容确定是否已付款,请确保在 check_payment 方法中重新加载它(这就是存在的原因),因为该对象可能不会意识到该属性在工作后的 5 分钟内已更改被预定了。这就是我调用self.reloadcheck_payment 方法的原因。

于 2012-10-15T20:57:11.087 回答