Ruby-on-rails Rails 3.0 中的 f.error_messages
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3873190/
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
f.error_messages in Rails 3.0
提问by Craig Smitham
Rails 3.0 deprecated f.error_messagesand now requires a plugin to work correctly - I however want to learn how to display error messages the (new) native way. I am following the getting started guide, which uses the deprecated method when implementing the comments form. For example:
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 %>
Here is the correct way to do it (as generated by the scaffold):
这是正确的方法(由脚手架生成):
<%= 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 %>
. . .
I understand that I use the @postvariable in the latter example, but what variable do I reference in the former to get the error messages for comment creation?
我知道我@post在后一个例子中使用了这个变量,但是我在前一个例子中引用了什么变量来获取评论创建的错误消息?
采纳答案by bunwich
I just looked into the docrails github issues, and they've decided to remove f.error_messages instead of explaining how to do validation for comments.
我刚刚查看了 docrails github 问题,他们决定删除 f.error_messages 而不是解释如何对评论进行验证。
回答by Nicolas Blanco
The best and clean way to implement error_messages in your form is by implementing error_messages in a FormBuilder.
在表单中实现 error_messages 的最好和干净的方法是在 FormBuilder 中实现 error_messages。
For example, here is the error_messages method I've implemented for my last project. By implemeting your own FormBuilder you can follow the rules and styles of your webdesigner... Here is an example that will output the errors list in ul/li's with some custom styles :
例如,这是我为上一个项目实现的 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
Then in my forms :
然后在我的表格中:
= f.error_messages
And that's all.
就这样。
回答by Lukas
I'm pretty sure all you'd need to do is reference @post.comments
我很确定你需要做的就是参考 @post.comments
So you could do something like:
所以你可以这样做:
<% @post.comments.each do |comment| %>
<% if comment.errors.any? %>
<% comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<% end %>
<% end %>
Or just pull all the errors out out:
或者只是把所有的错误都拉出来:
comment_errors = @post.comments.map(&:errors)
and then loop through them in your display logic to output each of the comment errors.
然后在显示逻辑中循环遍历它们以输出每个注释错误。
回答by Justin Tanner
This functionality exists as a standalone gem dynamic_form.
此功能作为独立的 gem dynamic_form存在。
Add the the following to your Gemfile
将以下内容添加到您的 Gemfile
gem 'dynamic_form'
From the github page:
DynamicForm holds a few helpers method to help you deal with your Rails3 models, they are:
DynamicForm 拥有一些辅助方法来帮助您处理 Rails3 模型,它们是:
input(record, method, options = {})form(record, options = {})error_message_on(object, method, options={})error_messages_for(record, options={})
input(record, method, options = {})form(record, options = {})error_message_on(object, method, options={})error_messages_for(record, options={})
It also adds f.error_messagesand f.error_message_onto your form builders.
它还添加f.error_messages和f.error_message_on到您的表单构建器。
回答by Benjamin
Here is my solution to the whole error scene.
这是我对整个错误场景的解决方案。
I created a partial which simply uses a model variable which one would pass when rendering it:
我创建了一个部分,它只使用一个模型变量,在渲染它时会传递它:
<%# 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 %>
You can easily add dynamic html class and/or id names based on the name of the model, as well as generic ones.
您可以根据模型的名称轻松添加动态 html 类和/或 id 名称,以及通用名称。
I have things setup where my error messages render in all the same place in a layout file:
我有一些设置,其中我的错误消息在布局文件中的所有相同位置呈现:
<%# app/views/layouts/application.html.erb %>
<%= yield :message %>
If one didn't want that functionality, removing the content_for in the partial would do the trick.
Then in really any view you want you can simply write:
如果不想要该功能,删除部分中的 content_for 就可以了。
然后在您想要的任何视图中,您都可以简单地编写:
<%= render 'errors/error', model: @some_model %>
One could further expand this by creating a partial which takes a collection and leverages the error partial above:
可以通过创建一个部分来进一步扩展它,该部分接受一个集合并利用上面的错误部分:
<%# app/views/errors/_collection.html.erb %>
<% collection.each do |model| %>
<%= render 'errors/error', model: model %>
<% end %>
Render it with:
渲染它:
<%= render 'errors/collection', collection: @some_model.some_has_many_association %>
I like this way. It is simple, easy to manage/maintain, and incredibly tweakable.
I hope this helps!
我喜欢这种方式。它很简单,易于管理/维护,并且非常易于调整。
我希望这有帮助!
EDIT: Everything in HAML
编辑: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
回答by Matt
I guess that the [@post, @post.comments.build]array is just passed to polymorphic_pathinside form_for. This generates a sub-resource path for comments (like /posts/1/commentsin this case). So it looks like your first example uses comments as sub-resources to posts, right?.
我猜[@post, @post.comments.build]数组只是传递给polymorphic_pathinside form_for。这会为评论生成一个子资源路径(就像/posts/1/comments在这种情况下)。所以看起来你的第一个例子使用评论作为帖子的子资源,对吧?。
So actually the controller that will be called here is the CommentsController. The reason why Lukas' solution doesn't work for you might be that you actually don't use @post.comments.build inside the controller when creating the comment (it doesn't matter that you use it in the view when calling form_for). The CommentsController#createmethod should look like this (more or less):
所以实际上这里将被调用的控制器是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
Then you can use the code generated by scaffolding, only replace @postinstance variable with @commentin all the lines except form_forcall.
然后就可以使用scaffolding生成的代码了,只@post需要@comment在除了form_forcall之外的所有行中替换instance变量。
I think it may also be a good idea to add the @comment = @post.comment.buildto the controller method that displays this form and use form_for([@post, @comment], ...)to keep the form contents displayed in the form if there're errors.
我认为将 加入@comment = @post.comment.build到显示此表单的控制器方法中也可能是一个好主意,并用于form_for([@post, @comment], ...)在出现错误时将表单内容保持在表单中。
If this doesn't work and you're not able to figure it out, please add your CommentsController#createmethod to the question.
如果这不起作用并且您无法弄清楚,请将您的CommentsController#create方法添加到问题中。

