状态机,模型validation和RSpec

这是我当前的类定义和规范:

class Event  :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 

当我运行规范时,我得到两次失败,一次成功。 我不知道为什么。 对于两个州, return if end_time.blank? end_time_before_final方法中的语句在每次都应为false时求值为true。 ‘推迟’是唯一似乎通过的州。 想知道这里会发生什么吗?

您似乎遇到了文档中提到的警告:

这里有一个重要的警告是,由于ActiveModel的validation框架中存在约束,当定义为在多个状态下运行时,自定义validation器将无法按预期工作。 例如:

  class Vehicle include ActiveModel::Validations state_machine do ... state :first_gear, :second_gear do validate :speed_is_legal end end end 

在这种情况下,:speed_is_legalvalidation仅针对:second_gear状态运行。 为避免这种情况,您可以像这样定义自定义validation:

  class Vehicle include ActiveModel::Validations state_machine do ... state :first_gear, :second_gear do validate {|vehicle| vehicle.speed_is_legal} end end end