Rails 3.0中的f.error_messages

时间:2010-10-06 13:54:27

标签: ruby-on-rails ruby ruby-on-rails-3

Rails 3.0已弃用f.error_messages,现在需要一个插件才能正常工作 - 但我想学习如何以(新)本机方式显示错误消息。我正在关注getting started guide,它在实现评论表单时使用了弃用的方法。例如:

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

6 个答案:

答案 0 :(得分:23)

在表单中实现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

就是这样。

答案 1 :(得分:13)

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

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

答案 2 :(得分:7)

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

将以下内容添加到Gemfile

gem 'dynamic_form'

来自github page

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

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

它还会向表单构建器添加f.error_messagesf.error_message_on

答案 3 :(得分:3)

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

我创建了一个partial,它只使用了一个模型变量,在渲染它时会传递它:

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

可以通过创建一个部分来进一步扩展这一点,该部分采用集合并利用上面的错误部分:

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

答案 4 :(得分:1)

我想[@post, @post.comments.build]数组只是传递给polymorphic_path内的form_for。这会为注释生成子资源路径(在本例中为/posts/1/comments)。所以看起来你的第一个例子使用评论作为帖子的子资源,对吧?

所以实际上在这里调用的控制器是CommentsController。 Lukas的解决方案不适合您的原因可能是您在创建注释时实际上不在控制器内部使用@ post.comments.build(在调用时在视图中使用它并不重要{ {1}})。 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], ...)方法。

答案 5 :(得分:0)

我刚刚查看了docrails github问题,他们决定删除f.error_messages,而不是解释如何对评论进行验证。