红宝石-Rails 3.0中的f.error_messages

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变量,但是在前一个示例中我引用了哪个变量来获取用于创建注释的错误消息?

Craig Smitham asked 2020-08-11T11:36:07Z
6个解决方案
23 votes

在表单中实现error_messages的最佳方法是在FormBuilder中实现error_messages。

例如,这是我为上一个项目实现的error_messages方法。通过实现自己的FormBuilder,您可以遵循Webdesigner的规则和样式。这是一个示例,将以某些自定义样式输出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

就这样。

Nicolas Blanco answered 2020-08-11T11:36:48Z
13 votes

我很确定您所要做的只是参考@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)

然后在显示逻辑中循环遍历它们,以输出每个注释错误。

Lukas answered 2020-08-11T11:37:21Z
7 votes

此功能作为独立的gem dynamic_form存在。

将以下内容添加到您的f.error_messages

gem 'dynamic_form'

从github页面:

DynamicForm拥有一些帮助程序方法来帮助您处理Rails3模型,它们是:

  • f.error_messages
  • f.error_messages
  • f.error_messages
  • f.error_messages

它还会将f.error_messagesf.error_message_on添加到您的表单构建器。

Justin Tanner answered 2020-08-11T11:37:59Z
3 votes

这是我对整个错误场景的解决方案。

我创建了一个部分,它仅使用模型变量,渲染时将传递该模型变量:

<%# 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类和/或id名称。

我进行了一些设置,将错误消息呈现在布局文件的所有相同位置:

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

<%= yield :message %>

如果不希望使用该功能,则可以通过删除局部代码中的content_for来达到目的。
然后,您实际上可以在任何视图中简单地编写:

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

可以通过创建一个接受集合并利用上面的错误partial的partial来进一步扩展它:

<%# 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 %>

我喜欢这样 它简单,易于管理/维护,并且调整得令人难以置信。
我希望这有帮助!

编辑: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
Benjamin answered 2020-08-11T11:39:05Z
1 votes

我猜想@post数组只是传递给CommentsController#create内部的form_for。这会生成一个用于评论的子资源路径(在这种情况下就像/posts/1/comments)。 因此,看起来您的第一个示例将评论用作帖子的子资源,对吗?

因此,实际上将在此处调用的控制器是@post。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

然后,您可以使用由脚手架生成的代码,仅在调用form_for([@post, @comment], ...)以外的所有行中将@post实例变量替换为3006615699604374545。

我认为将3006615699604374545添加到显示此表单的控制器方法中,并在出现错误时使用form_for([@post, @comment], ...)保持表单内容在表单中显示,也是一个好主意。

如果这不起作用,并且您无法弄清楚,请向问题中添加300661569960437454528方法。

Matt answered 2020-08-11T11:39:44Z
0 votes

我只是研究了docrails github问题,他们决定删除f.error_messages而不是解释如何对注释进行验证。

bunwich answered 2020-08-11T11:36:14Z
translate from https://stackoverflow.com:/questions/3873190/f-error-messages-in-rails-3-0