had*_*ees 1 ruby-on-rails state-machine e-commerce ruby-on-rails-4
我正在rails 4上写一个类似于kickstarter或indiegogo的电子商务平台.产品的状态在很大程度上取决于各种条件,例如订单是否足够.因此,例如,如果我使用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
Run Code Online (Sandbox Code Playgroud)
然后我可能会创建一个模型观察者,以便每次下订单时我都会检查product.has_enough_orders?,如果返回,true我会调用product.fund!.因此has_enough_orders?被多次检查.这似乎不是很有效.
另外product.launch!还有类似的问题.我能想到实现它的最好方法是使用类似的工具sidekiq来检查是否有任何预先推出的产品通过他们的launch_at时间.然而,这看起来同样很脏.
我只是在想它,或者你通常会如何使用状态机?
我只是修改了你的状态机以更好地处理条件.
你可以使用after_transition或before_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
Run Code Online (Sandbox Code Playgroud)