使用具有大量事务条件的状态机

时间:2013-07-08 18:01:54

标签: ruby-on-rails e-commerce ruby-on-rails-4 state-machine

我正在rails 4上编写一个类似于kickstarterindiegogo的电子商务平台。产品的状态在很大程度上取决于各种条件,例如订单是否足够。因此,例如,如果我使用gem state_machine,我的代码可能看起来像这样。

class Product  < ActiveRecord::Base
  has_many :orders

  state_machine :initial => :prelaunch do
    event :launch do
      transition :prelaunch => :pending, :if => lambda {|p| p.launch_at <= Time.now }
    end

    event :fund do
      transition :pending => :funded, :if => :has_enough_orders?
    end
  end

  def has_enough_orders?
    if orders.count > 10
  end
end

然后我可能会创建一个模型观察者,这样每次下订单时我都会检查product.has_enough_orders?,如果返回true,我会调用product.fund!。因此,has_enough_orders?被多次检查。这似乎不是很有效。

此外product.launch!也存在类似问题。我可以考虑实现它的最佳方法是使用类似sidekiq的内容,并且有一项工作可以检查是否有任何预启动的产品在launch_at时间内通过。然而,这似乎同样很脏。

我只是在想它,或者你通常会如何使用状态机?

1 个答案:

答案 0 :(得分:5)

我刚刚修改了状态机以更好地处理条件。

您可以使用after_transitionbefore_transition方法

class Product < ActiveRecord::Base
  has_many :orders

  state_machine :initial => :prelaunch do
    after_transition :prelaunch, :do => :check_launch
    after_transition :pending, :do => :has_enough_orders?

    event :launch do
      transition :prelaunch => :pending
    end

    event :fund do
      transition :pending => :funded
    end
  end

  def check_launch
    if launch_at <= Time.now
      self.launch # call event :launch
    else
      # whatever you want
    end
  end

  def has_enough_orders?
    if orders.count > 10
      self.fund # call event :fund
    else
      # whatever you want
    end
  end
end