Подтвердить что ты не робот

F.error_messages в Rails 3.0

Rails 3.0 не рекомендуется использовать f.error_messages и теперь для корректной работы плагина необходим. Однако я хочу узнать, как отображать сообщения об ошибках (новый). Я следую руководству по началу работы, в котором используется устаревший метод при реализации формы комментариев. Например:

<h2>Add a comment:</h2>
<%= form_for([@post, @post.comments.build]) do |f| %>
  <%= f.error_messages %>
<div class="field">
  <% f.label :commenter  %><br />
  <%= f.text_field :commenter  %>
</div>
<div class="field">
  <%= f.label :body %><br />
  <%= f.text_area :body %>
</div>
<div class="actions">
  <%= f.submit %>
</div>
<% end %>

Вот правильный способ сделать это (созданный эшафотом):

<%= form_for(@post) do |f| %>
  <% if @post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% @post.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
 . . . 

Я понимаю, что я использую переменную @post в последнем примере, но какую переменную я ссылаюсь в первом, чтобы получить сообщения об ошибках для создания комментариев?

4b9b3361

Ответ 1

Я просто просмотрел проблемы github docrails, и они решили удалить f.error_messages, а не объяснять, как делать проверки для комментариев.

Ответ 2

Лучший и чистый способ реализовать error_messages в вашей форме - это реализовать error_messages в FormBuilder.

Например, вот метод error_messages, который был реализован для моего последнего проекта. Внедрив собственный FormBuilder, вы можете следовать правилам и стилям вашего веб-дизайнера... Вот пример, который выводит список ошибок в ul/li с некоторыми пользовательскими стилями:

class StandardBuilder < ActionView::Helpers::FormBuilder
  def error_messages
    return unless object.respond_to?(:errors) && object.errors.any?

    errors_list = ""
    errors_list << @template.content_tag(:span, "There are errors!", :class => "title-error")
    errors_list << object.errors.full_messages.map { |message| @template.content_tag(:li, message) }.join("\n")

    @template.content_tag(:ul, errors_list.html_safe, :class => "error-recap round-border")
  end
end

Тогда в моих формах:

= f.error_messages

И все.

Ответ 3

Я уверен, что все, что вам нужно сделать, это ссылка @post.comments

Итак, вы можете сделать что-то вроде:

<% @post.comments.each do |comment| %>
    <% if comment.errors.any? %>

    <% comment.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
    <% end %>

    <% end %>
<% end %>

Или просто вытащите все ошибки:

comment_errors = @post.comments.map(&:errors)

а затем прокрутите их в логике отображения, чтобы вывести каждую из ошибок комментариев.

Ответ 4

Эта функциональность существует как автономный драгоценный камень dynamic_form.

Добавьте в свой Gemfile

следующее:
gem 'dynamic_form'

На странице github:

DynamicForm содержит несколько методов помощи, чтобы помочь вам справиться с вашими моделями Rails3:

  • input(record, method, options = {})
  • form(record, options = {})
  • error_message_on(object, method, options={})
  • error_messages_for(record, options={})

Он также добавляет f.error_messages и f.error_message_on к вашим сборщикам форм.

Ответ 5

Вот мое решение для всей сцены ошибок.

Я создал часть, которая просто использует переменную модели, которую она передавала бы при ее рендеринге:

<%# app/views/errors/_error.html.erb %>

<%= content_for :message do %>
  <% if model.errors.any? %>
    <ul>
      <% model.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    </ul>
  <% end %>
<% end %>

Вы можете легко добавлять динамические имена класса html и/или имена на основе имени модели, а также общие.

У меня есть настройки, где мои сообщения об ошибках отображаются на одном месте в файле макета:

<%# app/views/layouts/application.html.erb %>

<%= yield :message %>

Если кто-то не хотел, чтобы эта функциональность удаляла content_for в частичном, это сделало бы трюк.
Затем на самом деле вы можете просто написать:

<%= render 'errors/error', model: @some_model %>

Можно было бы еще больше расширить это, создав партию, которая берет коллекцию и использует ошибку, указанную выше:

<%# app/views/errors/_collection.html.erb %>

<% collection.each do |model| %>
  <%= render 'errors/error', model: model %>
<% end %>

Отрежьте его:

<%= render 'errors/collection', collection: @some_model.some_has_many_association %>

Мне нравится этот путь. Он прост, удобен в управлении/обслуживании и невероятно подстраивается.
Надеюсь, это поможет!

EDIT: все в HAML

-# app/views/errors/_error.html.haml

= content_for :message do
  - if model.errors.any?
    %ul
      - model.errors.full_messages.each do |msg|
        %li= msg


-# app/views/layouts/application.html.haml

= yield :message


= render 'errors/error', model: @some_model


-# app/views/errors/_collection.html.haml

- collection.each do |model|
  = render 'errors/errors', model: @some_model


= render 'errors/_collection', collection: @some_model.some_has_many_association

Ответ 6

Я предполагаю, что массив [@post, @post.comments.build] передается только polymorphic_path внутри form_for. Это генерирует субаресурсный путь для комментариев (например, /posts/1/comments в этом случае). Итак, похоже, что ваш первый пример использует комментарии в качестве вспомогательных ресурсов для сообщений, верно?.

Таким образом, на самом деле контроллер, который будет вызываться здесь, это CommentsController. Причина, по которой решение Lukas не работает для вас, может заключаться в том, что вы фактически не используете @post.comments.build внутри контроллера при создании комментария (неважно, что вы используете его в представлении при вызове form_for). Метод CommentsController#create должен выглядеть так (более или менее):

def create
  @post = Post.find(params[:post_id]
  @comment = @post.comments.build(params[:comment])

  if(@comment.save)
    # you would probably redirect to @post
  else
    # you would probably render post#show or wherever you have the form
  end
end

Затем вы можете использовать код, сгенерированный с помощью лесов, заменять только переменную экземпляра @post на @comment во всех строках, кроме form_for.

Я думаю, что также может быть хорошей идеей добавить @comment = @post.comment.build к методу контроллера, который отображает эту форму, и использовать form_for([@post, @comment], ...), чтобы содержимое формы отображалось в форме, если есть ошибки.

Если это не работает, и вы не можете понять это, добавьте свой метод CommentsController#create к вопросу.