使用state_machine进行条件验证

gjb*_*gjb 6 ruby ruby-on-rails state-machine ruby-on-rails-3

我正在使用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
Run Code Online (Sandbox Code Playgroud)

但是,这没有按预期工作:

> f = Foo.new
=> #<Foo id: nil, field1: nil, field2: nil, field3: nil, state: "step1", created_at: nil, updated_at: nil>
Run Code Online (Sandbox Code Playgroud)

Foo初始化为'step1'状态.到现在为止还挺好.

> f.next
=> false
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,由于验证过渡到下一步失败.

> f.errors.full_messages 
=> ["Field2 can't be blank"]
Run Code Online (Sandbox Code Playgroud)

但是,当我检查验证错误时,不是'Field1'未能按预期验证,而是'Field2'.它似乎正在运行正在转换到的状态的验证,而不是当前状态.

我究竟做错了什么?

非常感谢.

DGM*_*DGM 6

我只是在猜测,但也许它会运行验证

state :step2 do 
  validates_presence_of :field2
end
Run Code Online (Sandbox Code Playgroud)

什么时候尝试过渡到step2?

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

state :step2 do 
  validates_presence_of :field1
end
state :step3 do 
  validates_presence_of :field2
end
state :final do 
  validates_presence_of :field3
end
Run Code Online (Sandbox Code Playgroud)

  • 但验证可能是为了防止进入该状态,而不是退出该状态. (6认同)