2012-05-17 2 views
5

Ecco la mia definizione della classe attuale e spec:State Machine, Modello convalide e RSpec

class Event < ActiveRecord::Base 

    # ... 

    state_machine :initial => :not_started do 

    event :game_started do 
     transition :not_started => :in_progress 
    end 

    event :game_ended do 
     transition :in_progress => :final 
    end 

    event :game_postponed do 
     transition [:not_started, :in_progress] => :postponed 
    end 

    state :not_started, :in_progress, :postponed do 
     validate :end_time_before_final 
    end 
    end 

    def end_time_before_final 
    return if end_time.blank? 
    errors.add :end_time, "must be nil until event is final" if end_time.present? 
    end 

end 

describe Event do 
    context 'not started, in progress or postponed' do 
    describe '.end_time_before_final' do 
     ['not_started', 'in_progress', 'postponed'].each do |state| 
     it 'should not allow end_time to be present' do 
      event = Event.new(state: state, end_time: Time.now.utc) 
      event.valid? 
      event.errors[:end_time].size.should == 1 
      event.errors[:end_time].should == ['must be nil until event is final'] 
     end 
     end 
    end 
    end 
end 

Quando eseguo le specifiche, ottengo due fallimenti e un successo. Non ho idea del perché. Per due degli stati, l'istruzione return if end_time.blank? nel metodo end_time_before_final restituisce true quando dovrebbe essere falsa ogni volta. 'posticipato' è l'unico stato che sembra passare. Qualche idea su cosa potrebbe accadere qui?

+0

'before_transition: on =>: game_ended' sembra incompleto – apneadiving

+0

sono gli oggetti valido le caratteristiche del tuo fallimento? – apneadiving

+0

Rimossa la prima_transizione. Due degli oggetti sono validi per: end_time e uno è valido per: end_time. – keruilin

risposta

13

Sembra che si sta eseguendo in un avvertimento notato nel documentation:

Un importante avvertimento qui è che, a causa di un vincolo nel quadro di convalida di ActiveModel, validatori personalizzati non funzionerà come atteso quando definito per eseguire in più stati. Per esempio:

class Vehicle 
    include ActiveModel::Validations 

    state_machine do 
    ... 
    state :first_gear, :second_gear do 
     validate :speed_is_legal 
    end 
    end 
end 

In questo caso, il: convalida speed_is_legal otterrà eseguito solo per lo stato: second_gear. Per evitare questo, si può definire la convalida personalizzato in questo modo:

class Vehicle 
    include ActiveModel::Validations 

    state_machine do 
    ... 
    state :first_gear, :second_gear do 
     validate {|vehicle| vehicle.speed_is_legal} 
    end 
    end 
end 
+0

Dolce! Paga leggere Grazie per essere più attento di me. – keruilin