有状态机的条件验证

6
我将使用state_machine来构建一个多步骤表单,在转换到下一步之前,每个步骤的字段都需要进行验证。
以下是我的模型:
class Foo < ActiveRecord::Base
  state_machine :initial => :step1 do
    event :next do
      transition :step1 => :step2
      transition :step2 => :step3
    end
    event :previous do
      transition :step3 => :step2
      transition :step2 => :step1
    end

    state :step1 do 
      validates_presence_of :field1
    end
    state :step2 do 
      validates_presence_of :field2
    end
    state :step3 do 
      validates_presence_of :field3
    end
  end  
end

然而,这并没有按预期工作:
> f = Foo.new
=> #<Foo id: nil, field1: nil, field2: nil, field3: nil, state: "step1", created_at: nil, updated_at: nil>

Foo被初始化为'step1'状态。到目前为止一切正常。

> f.next
=> false

转到下一步骤由于验证失败而无法进行,这正是预料中的。
> f.errors.full_messages 
=> ["Field2 can't be blank"]

然而,当我检查验证错误时,没有像预期的那样未能通过验证的是“Field1”,而是“Field2”。它似乎在运行正在转换到的状态的验证,而不是当前状态的验证。我做错了什么?非常感谢。
1个回答

6

我只是猜测,也许它在这里运行验证

state :step2 do 
  validates_presence_of :field2
end

当尝试转换到步骤2时?

也许您不需要在第一步进行验证,而是将所有验证移动到下一步:

state :step2 do 
  validates_presence_of :field1
end
state :step3 do 
  validates_presence_of :field2
end
state :final do 
  validates_presence_of :field3
end

谢谢您的回答。虽然这提供了一种解决方法,但我想找出原因,因为它并不像文档所述那样运行。请参阅http://rdoc.info/github/pluginaweek/state_machine/master/StateMachine/Machine:state的“状态感知类方法”部分。 - gjb
运行 f.next 后,状态仍然是 'step1'。验证正在阻止转换。 - gjb
6
验证可能是为了防止进入该状态,而不是退出该状态。 - DGM
节省了时间!验证防止输入新状态。 - François Beausoleil
这其实很有道理。验证被定义为“为了处于这种状态,这个对象应该是什么”。当进行转换时,如果新状态的要求没有得到满足,则应该中止转换并回滚状态。 - D-side
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接