1

我正在 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时间。然而,这似乎同样肮脏。

我只是想多了还是这就是你通常使用状态机的方式?

4

1 回答 1

5

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

你可以使用after_transitionorbefore_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
于 2013-07-08T18:12:31.880 回答