2012-05-17 3 views
5

Hier ist meine aktuelle Klassendefinition und Spezifikation:State Machine, Modell-Validierungen und 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 

Wenn ich die spec laufen, bekomme ich zwei Ausfälle und ein Erfolg. Ich habe keine Idee warum. Für zwei der Zustände wird die return if end_time.blank?-Anweisung in der end_time_before_final-Methode als wahr ausgewertet, wenn sie jedes Mal falsch sein sollte. "aufgeschoben" ist der einzige Staat, der zu bestehen scheint. Irgendeine Idee, was hier passieren könnte?

+0

'before_transition: auf =>: game_ended' unvollständig scheint – apneadiving

+0

Sind die Objekte gültig in Ihrem Versagen Spezifikationen? – apneadiving

+0

Die before_transition wurde entfernt. Zwei der Objekte sind gültig für: end_time und eins ist gültig für: end_time. – keruilin

Antwort

13

Es sieht aus wie Sie in einen Nachteil in der documentation bemerkt laufen:

Ein wichtig Nachteil hier ist, dass aufgrund einer Einschränkung in ActiveModel Validierungs Rahmen, eigene Prüfer wird nicht als Arbeit erwartet, wenn definiert, um in mehreren Zuständen auszuführen. Zum Beispiel:

class Vehicle 
    include ActiveModel::Validations 

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

In diesem Fall ist die: second_gear Zustand: speed_is_legal Prüfung wird nur für das laufen lassen. Um dies zu vermeiden, können Sie Ihre benutzerdefinierte Validierung definieren wie folgt:

class Vehicle 
    include ActiveModel::Validations 

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

Sweet! Lohnt sich zu lesen. Danke, dass du aufmerksamer warst als ich. – keruilin