2012-08-09 12 views
5

Con la migrazione da Rails 2 a Rails 3 gli errori di convalida sono stati spostati da ActiveRecord :: Error a ActiveModel :: Errors.
In Rails 2 l'errore di convalida aveva un tipo e un messaggio (tra l'altro) e si potrebbe verificare il tipo di errore di convalida facendo qualcosa di simile al seguente:Come determinare ActiveModel :: Errori tipo di convalida

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

Ma con Rails 3 sembra tutto ma l'attributo e il messaggio non validi sono andati persi. Di conseguenza l'unico modo per determinare il tipo è quello di confrontare il messaggio di errore: (.? Ad esempio, cosa succede se si dispone di diversi convalide che utilizzano lo stesso messaggio)

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

Il che non è affatto l'ideale.

Domanda:
Esiste un modo migliore in Rails 3.0 per determinare il tipo di errore di convalida?

+0

Eventuali duplicati di [? Come verificare che la convalida non è riuscita a ActiveRecord] (http://stackoverflow.com/questions/4119379/how-to-test-which- validation-failed-in-activerecord) – lulalala

risposta

4

Verificare se è stato aggiunto? su ActiveModel :: Errori:

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

che ti permette di fare questo:

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

Questo farebbe il trucco (anche se si tratta solo di comparare i messaggi di convalida) ma non è stato eseguito il backport a 3.0 (che non ho menzionato specificamente, aggiornerò la domanda). – pricey

+0

La cosa brutta a riguardo è che si basa sul messaggio di testo tradotto. –

1

ne avevo bisogno, non solo a scopo di test, ma anche per l'API. Ho finito con patch di scimmia:

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) 
Problemi correlati