Ruby on rails 如何一次显示一条RubyonRails表单验证错误消息?

Ruby on rails 如何一次显示一条RubyonRails表单验证错误消息?,ruby-on-rails,ruby,rubygems,Ruby On Rails,Ruby,Rubygems,我想知道我是如何做到这一点的。有人能给我建议或给我指出正确的方向吗 我目前所做的(如下面的代码片段所示)允许我一次显示每个字段中的一个错误。这不完全是我想做的 我想一次显示一条错误消息。例如,“first name不能为空”,那么一旦解决了该错误,就应该显示错误数组中的下一个错误。这应该一直发生,直到所有错误都得到解决 <% @user.errors.each do |attr, msg| %> <%= "#{attr} #{msg}" if @user.errors[attr

我想知道我是如何做到这一点的。有人能给我建议或给我指出正确的方向吗

我目前所做的(如下面的代码片段所示)允许我一次显示每个字段中的一个错误。这不完全是我想做的

我想一次显示一条错误消息。例如,“first name不能为空”,那么一旦解决了该错误,就应该显示错误数组中的下一个错误。这应该一直发生,直到所有错误都得到解决

<% @user.errors.each do |attr, msg| %>
<%= "#{attr} #{msg}" if @user.errors[attr].first == msg %> 
<% end %>

ActiveRecord将验证错误存储在名为
errors
的数组中。如果您有一个
用户
模型,那么您将访问给定实例中的验证错误,如下所示:

@user = User.create[params[:user]] # create will automatically call validators

if @user.errors.any? # If there are errors, do something

  # You can iterate through all messages by attribute type and validation message
  # This will be something like:
  # attribute = 'name'
  # message = 'cannot be left blank'
  @user.errors.each do |attribute, message|
    # do stuff for each error
  end

  # Or if you prefer, you can get the full message in single string, like so:
  # message = 'Name cannot be left blank'
  @users.errors.full_messages.each do |message|
    # do stuff for each error
  end

  # To get all errors associated with a single attribute, do the following:
  if @user.errors.include?(:name)
    name_errors = @user.errors[:name]

    if name_errors.kind_of?(Array)
      name_errors.each do |error|
        # do stuff for each error on the name attribute
      end
    else
      error = name_errors
      # do stuff for the one error on the name attribute.
    end
  end
end

当然,如果您只想向用户显示第一个错误或其他什么,您也可以在视图中而不是在控制器中执行任何操作。

经过几个小时的实验,我发现了这一点

<% if @user.errors.full_messages.any? %>
  <% @user.errors.full_messages.each do |error_message| %>
    <%= error_message if @user.errors.full_messages.first == error_message %> <br />
  <% end %>
<% end %>


更好的是:

<%= @user.errors.full_messages.first if @user.errors.any? %>

一个更好的主意

如果要将错误消息放在文本字段下方,可以这样做

.row.spacer20top
  .col-sm-6.form-group
    = f.label :first_name, "*Your First Name:"
    = f.text_field :first_name, :required => true, class: "form-control"
    = f.error_message_for(:first_name)

什么是的
错误消息?
-->嗯,这是一个很好的黑客做一些很酷的东西

# Author Shiva Bhusal
# Aug 2016
# in config/initializers/modify_rails_form_builder.rb
# This will add a new method in the `f` object available in Rails forms
class ActionView::Helpers::FormBuilder
  def error_message_for(field_name)
    if self.object.errors[field_name].present?
      model_name              = self.object.class.name.downcase
      id_of_element           = "error_#{model_name}_#{field_name}"
      target_elem_id          = "#{model_name}_#{field_name}"
      class_name              = 'signup-error alert alert-danger'
      error_declaration_class = 'has-signup-error'

      "<div id=\"#{id_of_element}\" for=\"#{target_elem_id}\" class=\"#{class_name}\">"\
      "#{self.object.errors[field_name].join(', ')}"\
      "</div>"\
      "<!-- Later JavaScript to add class to the parent element -->"\
      "<script>"\
          "document.onreadystatechange = function(){"\
            "$('##{id_of_element}').parent()"\
            ".addClass('#{error_declaration_class}');"\
          "}"\
      "</script>".html_safe
    end
  rescue
    nil
  end
end
注意:这里使用的引导变量


我是这样决定的:

<% @user.errors.each do |attr, msg| %>
  <li>
    <%= @user.errors.full_messages_for(attr).first if @user.errors[attr].first == msg %>
  </li>
<% end %>


  • 这样,您就可以使用区域设置来显示错误消息。

    我使用的是Rails 4.2.0,您的代码对我不起作用。相反,我不得不将
    @user.errors.invalid?(:name)
    更改为
    @user.errors.include?(:name)
    ,这是我迄今为止看到的关于堆栈溢出的最详细的答案。很好。我找不到任何关于您使用的方法“.on()”的文档。它不会出现在ruby类“Hash”文档中?更好的是:
    -这是对象和错误长度无关的
    f
    是表单变量。
      .has-signup-error{
        .signup-error{
          background: transparent;
          color: $brand-danger;
          border: none;
        }
    
        input, select{
          background-color: $bg-danger;
          border-color: $brand-danger;
          color: $gray-base;
          font-weight: 500;
        }
    
        &.checkbox{
          label{
            &:before{
              background-color: $bg-danger;
              border-color: $brand-danger;
            }
          }
        }
    
    <% @user.errors.each do |attr, msg| %>
      <li>
        <%= @user.errors.full_messages_for(attr).first if @user.errors[attr].first == msg %>
      </li>
    <% end %>