Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional validation with state_machine

I'm using state_machine to build a multi-step form, with fields for each step validated before transitioning to the next step.

This is my model:

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

However, this isn't working as expected:

> f = Foo.new
=> #<Foo id: nil, field1: nil, field2: nil, field3: nil, state: "step1", created_at: nil, updated_at: nil>

Foo is initialised with a state of 'step1'. So far so good.

> f.next
=> false

Transitioning to the next step fails due to validation, just as expected.

> f.errors.full_messages 
=> ["Field2 can't be blank"]

However, when I check for validation errors, it isn't 'Field1' that has failed to validate as expected, but rather 'Field2'. It appears to be running the validations for the state that is being transitioned to, rather than the current state.

What am I doing wrong?

Many thanks.

like image 224
gjb Avatar asked Dec 24 '10 00:12

gjb


1 Answers

I'm just guessing, here, but maybe it runs the validation in

state :step2 do 
  validates_presence_of :field2
end

when trying to transition to step2 ?

Perhaps you don't need a validation on step one, but rather move all the validations one step:

state :step2 do 
  validates_presence_of :field1
end
state :step3 do 
  validates_presence_of :field2
end
state :final do 
  validates_presence_of :field3
end
like image 89
DGM Avatar answered Sep 19 '22 07:09

DGM