如何一次显示一个 Ruby on Rails 表单验证错误消息?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7878662/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I display Ruby on Rails form validation error messages one at a time?
提问by LondonGuy
I'm trying to understand how I can achieve this. Can anyone advise me or point me in the right direction?
我试图了解如何实现这一目标。任何人都可以给我建议或指出正确的方向吗?
What I currently do, which is shown in the code snippet below, allows me to display 1 error from each field at a time. It's not not quite exactly what I want to do.
我目前所做的(如下面的代码片段所示)允许我一次显示每个字段的 1 个错误。这并不完全是我想要做的。
I want to display 1 error message at a time. For example, “first name can't be blank”, then once that error has been resolved, the next error in the array of errors should be displayed. This should keep happening until all errors have been resolved.
我想一次显示 1 条错误消息。例如,“名字不能为空”,那么一旦解决了该错误,就应该显示错误数组中的下一个错误。这应该一直发生,直到所有错误都得到解决。
<% @user.errors.each do |attr, msg| %>
<%= "#{attr} #{msg}" if @user.errors[attr].first == msg %>
<% end %>
采纳答案by LondonGuy
After experimenting for a few hours I figured it out.
经过几个小时的实验,我想通了。
<% 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 %>
Even better:
更好的是:
<%= @user.errors.full_messages.first if @user.errors.any? %>
回答by Wade Tandy
ActiveRecord stores validation errors in an array called errors. If you have a Usermodel then you would access the validation errors in a given instance like so:
ActiveRecord 将验证错误存储在名为 的数组中errors。如果您有一个User模型,那么您将访问给定实例中的验证错误,如下所示:
@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
Of course you can also do any of this in the views instead of the controller, should you want to just display the first error to the user or something.
当然,如果您只想向用户显示第一个错误或其他内容,您也可以在视图而不是控制器中执行任何操作。
回答by illusionist
A better idea,
一个更好的主意,
if you want to put the error message just beneath the text field, you can do like this
如果您想将错误消息放在文本字段下方,您可以这样做
.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)
What is error_message_for?
--> Well, this is a beautiful hack to do some cool stuff
什么是error_message_for?
--> 嗯,这是一个做一些很酷的事情的漂亮技巧
# 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
Markup Generated after error
错误后生成的标记
<div id="error_user_email" for="user_email" class="signup-error alert alert-danger">has already been taken</div>
<script>document.onreadystatechange = function(){$('#error_user_email').parent().addClass('has-signup-error');}</script>
Corresponding SCSS
对应的 SCSS
.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;
}
}
}
Note: Bootstrap variables used here
注意:这里使用的引导变量
回答by nscherzer
I resolved it like this:
我是这样解决的:
<% @user.errors.each do |attr, msg| %>
<li>
<%= @user.errors.full_messages_for(attr).first if @user.errors[attr].first == msg %>
</li>
<% end %>
This way you are using the locales for the error messages.
这样您就可以使用语言环境来显示错误消息。


