복붙노트

[RUBY-ON-RAILS] 레일 유효성 검사의 순서를 제어

RUBY-ON-RAILS

레일 유효성 검사의 순서를 제어

나는 양식을 사용하여 사용자가 채워 7 개 숫자 속성을 가진 레일 모델을 가지고있다.

내가 사용하기 쉬운 분명히 이러한 각 속성의 존재를 검증 할 필요가

validates :attribute1, :presence => true
validates :attribute2, :presence => true
# and so on through the attributes

그러나 나는 또한 그들과 함께 몇 가지 계산을 속성의 번호를 받아 수행하는 사용자 정의 유효성 검사기를 실행해야합니다. 이러한 계산의 결과가 특정 범위 내에 있지 않은 경우,이 모델은 무효 선언해야한다.

그것은 자신의 일이 너무 쉽다

validate :calculations_ok?

def calculations_ok?
  errors[:base] << "Not within required range" unless within_required_range?
end

def within_required_range?
  # check the calculations and return true or false here
end

그러나 문제는 방법 "유효성 검사는"항상 방법 "유효성"전에 실행됩니다 있다는 것입니다. 필요한 필드를 비워 중 하나가, 레일 사용자 잎에서 오류가 발생하는 경우가 빈 속성으로 계산을 수행을 시도하는이 수단.

어떻게 내가 먼저 필요한 모든 속성의 존재를 확인할 수 있습니까?

해결법

  1. ==============================

    1.나는 확실히 그것은 (는) 자체 주문한 끝 해시를 속성 방법에 의존 하듯이 검증이 실행받을 차례를 보장 할 것 아니에요. 당신은 더 나은 귀하의 validate 메소드가 더 탄력 필요한 데이터의 일부가 누락 된 경우 간단하게 실행되지 만들고 해제 할 수있다. 예를 들면 :

    나는 확실히 그것은 (는) 자체 주문한 끝 해시를 속성 방법에 의존 하듯이 검증이 실행받을 차례를 보장 할 것 아니에요. 당신은 더 나은 귀하의 validate 메소드가 더 탄력 필요한 데이터의 일부가 누락 된 경우 간단하게 실행되지 만들고 해제 할 수있다. 예를 들면 :

    def within_required_range?
      return if ([ a, b, c, d ].find(&:blank?))
    
      # ...
    end
    

    이 (D) 내지 (A)의 임의의 변수 등등 닐 빈 어레이 또는 문자열 등이 포함 빈 경우 구제한다.

  2. ==============================

    2.약간 더 복잡한 상황에 대한 대안은 첫째 종속 속성에 대한 유효성 검사를 실행하는 도우미 메서드를 작성하는 것입니다. calculations_ok : 그럼 당신은 당신을 만들 수 있습니까? 검증 조건부 실행합니다.

    약간 더 복잡한 상황에 대한 대안은 첫째 종속 속성에 대한 유효성 검사를 실행하는 도우미 메서드를 작성하는 것입니다. calculations_ok : 그럼 당신은 당신을 만들 수 있습니까? 검증 조건부 실행합니다.

    validates :attribute1, :presence => true
    validates :attribute2, :presence => true
    ...
    validates :attribute7, :presence => true
    
    validate :calculations_ok?, :unless => Proc.new { |a| a.dependent_attributes_valid? }
    
    def dependent_attributes_valid?
      [:attribute1, ..., :attribute7].each do |field|
        self.class.validators_on(field).each { |v| v.validate(self) }
        return false if self.errors.messages[field].present?
      end
      return true
    end
    

    나는 종속 속성에 대한 검증이 매우 복잡했기 때문에 프로젝트에 대한이 같은 무언가를 창조했다. 내 상당의 : calculations_ok? 종속 속성이 제대로 확인하지 않은 경우에 예외를 던질 것입니다.

    장점 :

    주의 사항 :

  3. ==============================

    3.http://railscasts.com/episodes/211-validations-in-rails-3 체크 아웃

    http://railscasts.com/episodes/211-validations-in-rails-3 체크 아웃

    사용자 정의 유효성 검사기를 구현 한 후, 당신은 간단하게 할 수 있습니다

    validates :attribute1, :calculations_ok => true
    

    그게 당신의 문제를 해결해야한다.

  4. ==============================

    4.제임스 H 솔루션은 나에게 가장 의미가 있습니다. 그러나 고려해야 할 하나의 여분의 것, 당신은 종속 검증에 조건이있는 경우, 그들은 dependent_attributes_valid에 대한 위해도 점검 할 필요가있다? 작업을 호출합니다.

    제임스 H 솔루션은 나에게 가장 의미가 있습니다. 그러나 고려해야 할 하나의 여분의 것, 당신은 종속 검증에 조건이있는 경우, 그들은 dependent_attributes_valid에 대한 위해도 점검 할 필요가있다? 작업을 호출합니다.

    즉.

        validates :attribute1, presence: true
        validates :attribute1, uniqueness: true, if: :attribute1?
        validates :attribute1, numericality: true, unless: Proc.new {|r| r.attribute1.index("@") }
        validates :attribute2, presence: true
        ...
        validates :attribute7, presence: true
    
        validate :calculations_ok?, unless: Proc.new { |a| a.dependent_attributes_valid? }
    
        def dependent_attributes_valid?
          [:attribute1, ..., :attribute7].each do |field|
            self.class.validators_on(field).each do |v|
              # Surely there is a better way with rails?
              existing_error = v.attributes.select{|a| self.errors[a].present? }.present?
    
              if_condition = v.options[:if]
              validation_if_condition_passes = if_condition.blank?
              validation_if_condition_passes ||= if_condition.class == Proc ? if_condition.call(self) : !!self.send(if_condition)
    
              unless_condition = v.options[:unless]
              validation_unless_condition_passes = unless_condition.blank?
              validation_unless_condition_passes ||= unless_condition.class == Proc ? unless_condition.call(self) : !!self.send(unless_condition)
    
              if !existing_error and validation_if_condition_passes and validation_unless_condition_passes
                v.validate(self)
              end
            end
            return false if self.errors.messages[field].present?
          end
          return true
        end
    
  5. from https://stackoverflow.com/questions/5966055/controlling-the-order-of-rails-validations by cc-by-sa and MIT license