如何根据其他属性值添加自定义验证消息?

时间:2012-12-22 10:20:20

标签: ruby-on-rails ruby validation implementation state-machine

我正在使用Ruby on Rails 3.2.9而我只是尝试使用state_machine gem。我有以下声明:

# Model class attributes are:
#
# [String]  status
# [Boolean] checkin_1
# [Boolean] checkin_2
#
class Article < ActiveRecord::Base
  state_machine :attribute => :status, :initial => :unconfirmed do
    state :confirmed, :value => 'confirmed'
    state :unconfirmed, :value => 'unconfirmed'

    event :confirm do
      transition :unconfirmed => :confirmed
    end

    event :unconfirm do
      transition :confirmed => :unconfirmed
    end
  end
end

我想在触发confirm事件并checkin_1和/或checkin_2值为{{1}时向实例对象添加自定义验证消息(避免保存这些对象) }}。也就是说,考虑到我正在尝试false以下每个对象:

confirm

然后我想避免保存对象并分别添加错误消息,如下所示:

<#Article id: 1, :status: 'unconfirmed', checkin_1: false, checkin_2: false>
<#Article id: 1, :status: 'unconfirmed', checkin_1: false, checkin_2: true>
<#Article id: 1, :status: 'unconfirmed', checkin_1: true, checkin_2: false>

我应该如何

2 个答案:

答案 0 :(得分:1)

这样做怎么样:

state confirmed do
  validate do
    if !checkin_1 and !checkin_2
       msg = "can not be confirmed if it is not checked for 1 and 2"
       errors.add(:checkin_1, msg)
       errors.add(:checkin_2, msg)
    elsif !checkin_1
       errors.add(:checkin_1, "can not be confirmed if it is not checked for 1")
    elsif !checkin_2
       errors.add(:checkin_2, "can not be confirmed if it is not checked for 2")
    end
  end
end

答案 1 :(得分:0)

    class Article < ActiveRecord::Base
      attr_accessor :checkin_1
      attr_accessor :checkin_2

      state_machine :attribute => :status, :initial => :unconfirmed do
        state :confirmed, :value => 'confirmed'
        state :unconfirmed, :value => 'unconfirmed'

        before_transition any => :confirm do |article|
          return false unless article.custom_validate?
        end

        event :confirm do
          transition :unconfirmed => :confirmed
        end

        event :unconfirm do
          transition :confirmed => :unconfirmed
        end
      end

      private

      def custom_validate?
        validate_flag = true

        if self.checkin_1 and self.checkin_2
          msg = "can not be confirmed if it is not checked for 1 and 2"
          errors.add(:checkin_1, msg)
          errors.add(:checkin_2, msg)
          validate_flag = false
        elsif !checkin_1
          errors.add(:checkin_1, "can not be confirmed if it is not checked for 1")
          validate_flag = false
        elsif !checkin_2
          errors.add(:checkin_2, "can not be confirmed if it is not checked for 2")
          validate_flag = false
        end

        validate_flag
      end
    end