Проверка правильности Rails и обертки выбора 'fieldWithErrors' - PullRequest
6 голосов
/ 14 апреля 2009

Это нормальное поведение, чтобы не получить <div class="fieldWithErrors"> обернутые тэги arround select с ошибками валидации? Лично я не вижу причин, по которым теги select должны обрабатываться иначе, чем другие теги формы (input, textarea).

I do получить ошибку в error_messages_for и error_message_on методах для этого поля.

PS. Я немного изменил ActionView::Base.field_error_proc, чтобы получить теги span вместо div, но это не проблема.

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>"
}

Ответы [ 5 ]

4 голосов
/ 17 декабря 2009

Проблема (по крайней мере для меня) заключалась в том, что мой f.select :whatever_id искал в объекте object.errors ключ :whatever_id, когда моя проверка была на самом деле :whatever, а не :whatever_id.

Я обошел эту досадную проблему, изменив

object.errors.on(@method_name)

до

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

Вот разница (против 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
3 голосов
/ 25 апреля 2009

Поскольку я не мог выяснить, почему теги select не были включены в этот Proc, я создал вспомогательный метод, который делает то же самое.

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

Я использую его в своих представлениях так:

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

Если кто-нибудь знает лучший или более чистый способ сделать это, я открыт для предложений.

2 голосов
/ 14 апреля 2009

Я нашел это сообщение в блоге, которое, кажется, обращается к этому:

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

Надеюсь, это полезно!

1 голос
/ 14 февраля 2012

Так я решаю эту проблему.

Я создаю специальную обертку выбора field_with_errors:

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

CSS:

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

И я изменяю свои проверки: любой_ид вместо : любой

validates :whatever_id, :presence => true

Я забыл, выберите:

f.collection_select(:whatever_id, Whatever.all, :id, :name, prompt: t(:please_choose))
0 голосов
/ 12 августа 2009

Другой способ, может быть вставлен на уровне метода или контроллера или в environment.rb:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...