views:

1665

answers:

4

Is it normal behaviour to not get the <div class="fieldWithErrors"> wrapped arround select tags that have validation errors? I personally see no reason why the select tags should be treated differently than other form tags (input, textarea).

I do get the error in error_messages_for and error_message_on methods for that field.

PS. I have altered a bit the ActionView::Base.field_error_proc in order to get span tags instead of divs, but that isn't the problem.

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>"
}
+1  A: 

Hi Andi, I found this blog post which appears to address this:

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

Hope it is helpful!

Adam Alexander
Hi. Thanks for the reply! I found that too, but he doesn't really specify if and how he got it working. There is one link to the rails wiki, but it is broken. I would like to avoid as much as possible adding a test on 'error_message_on' for every select because that would really complicate my views.
andi
+2  A: 

Because I couldn't find out why the select tags were not included in that Proc, I created a helper method which does preety much the same thing.

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

I use it in my views like so:

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

If anybody knows a better or cleaner way to do it, I'm open to suggestions.

andi
A: 

Another way, can be inserted at method or controller level, or in the environment.rb:

ActionView::Base.field_error_proc = proc { |input, instance| input }

+1  A: 

The problem (for me at least) was that my f.select :whatever_id was looking in the object.errors object for a key of :whatever_id when my validation was actually on :whatever, not :whatever_id.

I worked around this annoying problem by changing

object.errors.on(@method_name)

to

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

Here's the diff (against Rails 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
Tyler Rick