2012-08-09 5 views
5

레일 2에서 레일즈 3 로의 마이그레이션에서 유효성 검사 오류가 ActiveRecord :: Error에서 ActiveModel :: Errors로 이동되었습니다. 검증 오류 2 레일에서
는 (다른 것들 사이) 유형과 메시지를 가지고 당신은 같은 것을 수행하여 유효성 검사 오류의 유형을 확인할 수 있습니다 다음ActiveModel :: 오류 확인 유형을 결정하는 방법

rescue ActiveRecord::RecordInvalid => e 
    e.record.errors.each do |attr, error| 
    if error.type == :foo 
     do_something 
    end 
    end 
end 

그러나 레일 3은 모든 것을 유효하지 않은 속성 W 메시지가 유실되었습니다. 그 결과 유형을 결정하는 유일한 방법은 오류 메시지 비교하는 것입니다 : (.? 예를 들어, 당신은 동일한 메시지를 사용하는 여러 검증 할 경우 어떻게)

rescue ActiveRecord::RecordInvalid => e 
    e.record.errors.each do |attr, error| 
    if error == "foobar" 
     do_something 
    end 
    end 
end 

전혀 적합하지 않습니다.

질문 :
는 유효성 검사 오류의 유형을 결정하는 레일 3.0에서 더 나은 방법이 있나요?

+0

가능한 복제 [? 액티브에 실패한 검증 테스트 방법] (http://stackoverflow.com/questions/4119379/how-to-test-which- : 나는 원숭이 패치 결국 한 validation-failed-in-activerecord) – lulalala

답변

4

추가 확인 하시겠습니까? 이 작업을 수행 할 수 있습니다

https://github.com/rails/rails/blob/master/activemodel/lib/active_model/errors.rb#L331

: ActiveModel :: 오류에

record.errors.added?(:field, :error) 
+0

트릭을 할 것입니다 (검증 메시지 만 비교하고 있음에도 불구하고)하지만 3.0으로 백 포트되지 않았습니다 (특별히 언급하지는 않았지만 질문을 업데이트 할 것입니다). – pricey

+0

번역 된 텍스트 메시지를 사용하는 것이 좋지 않습니다. –

1

나는뿐만 아니라 테스트 용뿐만 아니라 API에 필요한.

module CoreExt 
    module ActiveModel 
    module Errors 
     # When validation on model fails, ActiveModel sets only human readable 
     # messages. This does not allow programmatically identify which 
     # validation rule exactly was violated. 
     # 
     # This module patches {ActiveModel::Errors} to have +details+ property, 
     # that keeps name of violated validators. 
     # 
     # @example 
     # customer.valid? # => false 
     # customer.errors.messages # => { email: ["must be present"] } 
     # customer.errors.details # => { email: { blank: ["must be present"] } } 
     module Details 
     extend ActiveSupport::Concern 

     included do 
      if instance_methods.include?(:details) 
      fail("Can't monkey patch. ActiveModel::Errors already has method #details") 
      end 

      def details 
      @__details ||= Hash.new do |attr_hash, attr_key| 
       attr_hash[attr_key] = Hash.new { |h, k| h[k] = [] } 
      end 
      end 

      def add_with_details(attribute, message = nil, options = {}) 
      error_type = message.is_a?(Symbol) ? message : :invalid 
      normalized_message = normalize_message(attribute, message, options) 
      details[attribute][error_type] << normalized_message 

      add_without_details(attribute, message, options) 
      end 
      alias_method_chain :add, :details 

      def clear_with_details 
      details.clear 
      clear_without_details 
      end 
      alias_method_chain :clear, :details 
     end 
     end 
    end 
    end 
end 

# Apply monkey patches 
::ActiveModel::Errors.send(:include, ::CoreExt::ActiveModel::Errors::Details) 
관련 문제