Как отображать сообщения об ошибках проверки формы Ruby on Rails по одному
Я пытаюсь понять, как я могу это достичь. Может ли кто-нибудь посоветовать мне или указать мне в правильном направлении?
Это позволяет одновременно отображать одну ошибку из каждого поля. Это почти то, что я хочу сделать, но не совсем точно. Я хочу отображать 1 сообщение об ошибке за раз. НАПРИМЕР. имя не может быть пустым. Как только это было разрешено, он переходит к следующей ошибке. Поэтому, если пользователь добавит числа к своей фамилии, он больше не будет пустым, но он покажет еще одну ошибку, указав, что разрешены только буквы и т.д. Когда эта ошибка была исправлена, она перешла бы к ошибке имени или, может быть, к электронной почте, если поле пользователя правильно их фамилию.
<% @user.errors.each do |attr, msg| %>
<%= "#{attr} #{msg}" if @user.errors[attr].first == msg %>
<% end %>
Ответы
Ответ 1
После эксперимента в течение нескольких часов я понял это.
<% 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? %>
Ответ 2
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.on(: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
Конечно, вы также можете сделать что-либо из этого в представлениях вместо контроллера, если вы хотите просто отобразить первую ошибку для пользователя или что-то в этом роде.
Ответ 3
Лучшая идея,
если вы хотите поместить сообщение об ошибке только под текстовое поле, вы можете сделать это следующим образом:
.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)
Что такое 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
Результат
![введите описание изображения здесь]()
Разметка, созданная после ошибки
<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>
Соответствующий 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;
}
}
}
Примечание: здесь используются загрузочные переменные
Ответ 4
Я решил это следующим образом:
<% @user.errors.each do |attr, msg| %>
<li>
<%= @user.errors.full_messages_for(attr).first if @user.errors[attr].first == msg %>
</li>
<% end %>
Таким образом вы используете локали для сообщений об ошибках.