【问题标题】:Rails validation and 'fieldWithErrors' wrapping select tagsRails 验证和'fieldWithErrors'包装选择标签
【发布时间】:2010-10-19 08:00:30
【问题描述】:

没有得到具有验证错误的<div class="fieldWithErrors"> 包装的环绕选择标签是否属于正常行为?我个人认为没有理由将选择标签与其他表单标签(输入、文本区域)区别对待。

确实在该字段的error_messages_forerror_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>"
}

【问题讨论】:

    标签: ruby-on-rails validation actionview field-with-errors


    【解决方案1】:

    问题(至少对我而言)是我的f.select :whatever_idobject.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
    

    【讨论】:

      【解决方案2】:

      因为我不知道为什么选择标签没有包含在那个 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 %>
      

      如果有人知道更好或更清洁的方法,我愿意接受建议。

      【讨论】:

        【解决方案3】:

        我发现这篇博客文章似乎解决了这个问题:

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

        希望对你有帮助!

        【讨论】:

        • 嗨。谢谢回复!我也发现了这一点,但他并没有具体说明他是否以及如何使其工作。 rails wiki 有一个链接,但它已损坏。我想尽可能避免为每个选择添加一个关于 'error_message_on' 的测试,因为这真的会使我的观点复杂化。
        • 他确实指定了如何让它在这里工作:“唯一的解决方案是将 working_time 模型中的验证从 project 更改为 project_id”。即在模型类中,将“validates_presence_of :project”改为“validates_presence_of :project_id”
        【解决方案4】:

        这就是我解决这个问题的方法。

        我创建了一个特定的“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;
        }
        

        我将我的验证修改为 :whatever_id 而不是 :whatever

        validates :whatever_id, :presence => true
        

        我忘记了,选择:

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

        【讨论】:

        • 谢谢,我发现修改 if 以在 html_tag 中包含对“无错误”类的检查很方便,当发现时根本不显示任何错误。当某些表单字段上有诸如javascript datepickers之类的东西时非常方便,额外的标记会破坏。
        【解决方案5】:

        另一种方式,可以在方法或控制器级别插入,也可以在 environment.rb 中插入:

        ActionView::Base.field_error_proc = proc { |输入,实例|输入 }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-20
          • 2015-06-27
          • 2017-10-20
          • 2019-09-17
          • 1970-01-01
          相关资源
          最近更新 更多