Pregunta

¿Es un comportamiento normal de no conseguir la <div class="fieldWithErrors"> envuelto arround seleccione las etiquetas que tienen errores de validación? Yo personalmente veo ninguna razón por la cual las etiquetas de selección deben ser tratados de manera diferente que otras etiquetas de formulario (de entrada, área de texto).

DO obtener el error en los métodos y error_messages_for error_message_on para ese campo.

PS. He alterado un poco el ActionView::Base.field_error_proc el fin de obtener etiquetas span lugar de divs, pero ese no es el problema.

ActionView::Base.field_error_proc = Proc.new { |html_tag, instance|
   #if I puts html_tag here I only get the <input> tags
   "<span class=\"fieldWithErrors\">#{html_tag}</span>"
}
¿Fue útil?

Solución 2

Debido a que no pude averiguar por qué las etiquetas de selección no se incluyeron en que Proc, he creado un método auxiliar que hace preety o menos lo mismo.

def field_with_error(object, method, &block)
  if block_given?
    if error_message_on(object, method).empty?
      concat capture(&block)
    else
      concat '<span class="fieldWithErrors">' + capture(&block) + '</span>'
    end
  end
end

Yo lo uso en mis puntos de vista, así:

<% field_with_error @some_object, :assoc do %>
  <%= f.select(:assoc_id, @associations.collect {|assoc| [ asoc.name, assoc.id ] }) %>
<% end %>

Si alguien conoce una manera mejor o más limpia de hacerlo, estoy abierto a sugerencias.

Otros consejos

El problema (al menos para mí) es que mi f.select :whatever_id estaba buscando en el objeto object.errors para una clave de validación :whatever_id cuando mi era en realidad en :whatever, no :whatever_id.

He trabajado en torno a este molesto problema cambiando

object.errors.on(@method_name)

a

object.errors.on(@method_name) || object.errors.on(@method_name.gsub(/_id$/, ''))

Aquí está el diff (contra rieles 2.3.4):

diff --git a/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb
index 541899e..5d5b27e 100644
--- a/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -247,7 +247,7 @@ module ActionView
       alias_method :tag_without_error_wrapping, :tag
       def tag(name, options)
         if object.respond_to?(:errors) && object.errors.respond_to?(:on)
-          error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name))
+          error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name) || object.errors.on(@method_name.gsub(/_id$/, '')))
         else
           tag_without_error_wrapping(name, options)
         end
@@ -256,7 +256,7 @@ module ActionView
       alias_method :content_tag_without_error_wrapping, :content_tag
       def content_tag(name, value, options)
         if object.respond_to?(:errors) && object.errors.respond_to?(:on)
-          error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name))
+          error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name) || object.errors.on(@method_name.gsub(/_id$/, '')))
         else
           content_tag_without_error_wrapping(name, value, options)
         end

He encontrado esta entrada del blog que aparece para hacer frente a esto:

http://blog.invalidobject.com/2007/09/16/rails-error-wrapping-for-select-input-fields-of-referenced-models

Espero que sea útil!

Esta es la forma en que resolver ese problema.

crear un "field_with_errors" específicos de selección envoltorio:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
   if html_tag =~ /^<input/
     %{<div class="field_with_errors">#{html_tag}<label for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</label></div>}.html_safe
   elsif html_tag =~ /^<select/
 %{<div class="field_with_errors" id="select-error">#{html_tag}</div>}.html_safe
   else
     %{<div class="field_with_errors">#{html_tag}</div>}.html_safe
   end
end

El CSS:

#select-error {
    border: 1px solid red;
    overflow-y: auto;
    overflow-x: hidden;
}

Y modifico mis validaciones a: whatever_id en lugar de lo

validates :whatever_id, :presence => true

Se me olvidaba, el selecto:

f.collection_select(:whatever_id, Whatever.all, :id, :name, prompt: t(:please_choose))

Otra manera, se puede insertar en el método o controlador de nivel, o en el environment.rb:

ActionView :: Base.field_error_proc = proc {| entrada, instancia | entrada}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top