2012-08-09 10 views
5

Con la migración de Rails 2 a Rails, 3 errores de validación se movieron de ActiveRecord :: Error a ActiveModel :: Errors.
En los carriles 2 el error de validación tenían un tipo y un mensaje (entre otras cosas) y se podía comprobar el tipo del error de validación haciendo algo como lo siguiente:Cómo determinar ActiveModel :: Tipo de validación de errores

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

Pero con Rails 3 parece que todo pero el atributo inválido y el mensaje se han perdido. Como resultado, la única manera de determinar el tipo es comparar el mensaje de error: (.? Por ejemplo, lo que si tiene varias validaciones que utilizan el mismo mensaje)

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

Lo cual no es del todo ideal.

Pregunta:
¿Hay una mejor manera de carriles 3.0 para determinar el tipo de error de validación?

+0

duplicado posible de [? Cómo poner a prueba lo que la validación falló en ActiveRecord] (http://stackoverflow.com/questions/4119379/how-to-test-which- validation-failed-in-activerecord) – lulalala

Respuesta

4

¿Está buscando agregar? en ActiveModel :: Errores:

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

que le permite hacer esto:

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

Eso haría el truco (aunque también es solo la comparación de los mensajes de validación) pero no se ha transferido a 3.0 (que no mencioné específicamente, actualizaré la pregunta). – pricey

+0

Lo malo de esto es que depende del mensaje de texto traducido. –

1

lo necesitaba no sólo con fines de prueba, sino también para la API. He terminado con el parche mono:

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) 
Cuestiones relacionadas