`
Hooopo
  • 浏览: 335264 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

可定制的Rails错误回显

阅读更多
通常rails页面的错误信息提示都是放在首部用 error_message_for,生成这样的错误提示:


这样很快就把所有错误信息都显示出来了。但是有一个缺点,就是灵活性太差。感觉error_message_for就像rails的scaffold一样可以快速搭建一个curd应用,但是定制性不高。

还好,rails的可扩展能力是很强的,你不喜欢里面的某一方法,你甚至可以去把他的源代码改了(当然不推荐这样做...),所以只有自己动手..

看了下源码:

# Returns the Errors object that holds all information about attribute error messages.
    def errors
      @errors ||= Errors.new(self)
   end


这一句就够了:原来每个ActiveRecord的实例都有一个errors方法。这个@errors就是所有rails其他错误信息处理封装的基础。

自己写了一个对每个model的field错误信息提取到div的方法,同时把汉化也加进去了,很简单。。
module ApplicationHelper
  def error_div(model, field, field_name)
    return unless model
    field = field.is_a?(Symbol) ? field.to_s : field
    errors = model.errors[field]
    return unless errors
    %Q(
    <div class="errors">
    #{errors.is_a?(Array) ? errors.map{|e| field_name + e}.join(",") : field_name << errors}
    </div>
    )
  end
end



demo:
validation:
class Post < ActiveRecord::Base
  validates_presence_of :title, :message => "不能为空"
  validates_length_of   :title, :in => 2..10, :message => "长度不正确"
end


view:

<% form_for(@post) do |f| %>

  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %><%= error_div(@post, :title, "标题")%>
  </p>
  <p>
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </p>
  <p>
    <%= f.submit 'Create' %>
  </p>
<% end %>


效果1:

效果2:



分享到:
评论
22 楼 lzqustc 2009-09-23  
<p>class User &lt; ActiveRecord::Base<br>   validates_presence_of     :email,  :message =&gt; "邮箱不能为空!"<br>   ......<br>end<br><br> %tr<br>     %td{ :height =&gt; "30", :align =&gt; "right", :valign =&gt; "middle" }<br>          %strong{:style =&gt;"color: red;"}*<br>           E-mail:<br>      %td{ :height =&gt; "30", :align =&gt; "left", :valign =&gt; "middle" }<br>           = user_form.text_field :email , :size =&gt; "20"<br>          <span style="color: #ff0000;">  %span{:style =&gt;"color: red;"}<br>            = @user.errors[:email]</span></p>
<p>效果如下:</p>
<p> </p>
<p><img src="http://dl.iteye.com/upload/attachment/149600/691489b4-5c20-3053-a3be-19a214b2f83e.bmp" alt=""></p>
<p> </p>
<p>不知,大家觉得如何?</p>
21 楼 星情泪 2009-09-20  
<div class="quote_title">amonlei 写道</div>
<div class="quote_div">
<p>8.3 Customizing the Error Messages HTML<br><br>By default, form fields with errors are displayed enclosed by a div element with the fieldWithErrors CSS class. However, it’s possible to override that.<br><br>The way form fields with errors are treated is defined by ActionView::Base.field_error_proc. This is a Proc that receives two parameters:<br><br>    * A string with the HTML tag<br>    * An instance of ActionView::Helpers::InstanceTag.<br><br>Here is a simple example where we change the Rails behaviour to always display the error messages in front of each of the form fields with errors. The error messages will be enclosed by a span element with a validation-error CSS class. There will be no div element enclosing the input element, so we get rid of that red border around the text field. You can use the validation-error CSS class to style it anyway you want.<br>ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| if instance.error_message.kind_of?(Array) %(#{html_tag}&lt;span class="validation-error"&gt;&amp;nbsp; #{instance.error_message.join(',')}&lt;/span&gt;) else %(#{html_tag}&lt;span class="validation-error"&gt;&amp;nbsp; #{instance.error_message}&lt;/span&gt;) end end<br><br>This will result in something like the following:</p>
<p><img src="http://guides.rubyonrails.org/images/validation_error_messages.png" alt="" width="410" height="53"><br><br>Validation error messages</p>
<p> </p>
</div>
<p> </p>
<p>非常棒!这样以后再写模型验证的时候,就可以把同一类型的写到一块了。</p>
<p>以前总是这么写</p>
<pre name="code" class="ruby">validates_numericality_of :weight, :message =&gt; "重量 必须是数字"
validates_numericality_of :num, :message =&gt; "购买数量 必须是数字"</pre>
<p> 虽然验证的内容是一个类型的,但是因为字段名不一样,所以还得自己加上,现在可以全部加到一起了</p>
<pre name="code" class="ruby">validates_numericality_of :num, :weight, :message =&gt; "必须是数字"</pre>
<p> 反正错误信息会出现到表单元素的后面,方便很多,呵呵</p>
20 楼 amonlei 2009-09-17  
Hooopo 写道
amonlei 写道
很明显,楼主没有去阅读过 rails文档

文档都是用来查的.....
原来是error_message_on啊!
引用

error_message_on(object, method, *args)
Returns a string containing the error message attached to the method on the object if one exists. This error message is wrapped in a DIV tag, which can be extended to include a :prepend_text and/or :append_text (to properly explain the error), and a :css_class to style it accordingly. object should either be the name of an instance variable or the actual object. The method can be passed in either as a string or a symbol. As an example, let’s say you have a model @post that has an error message on the title attribute:

  <%= error_message_on "post", "title" %>
  # => <div class="formError">can't be empty</div>

  <%= error_message_on @post, :title %>
  # => <div class="formError">can't be empty</div>

  <%= error_message_on "post", "title",
      :prepend_text => "Title simply ",
      :append_text => " (or it won't work).",
      :css_class => "inputError" %>




<%= error_message_on "post", "title", 
      :prepend_text => "Title simply ", 
      :append_text => " (or it won't work).", 
      :css_class => "inputError" %> 

啊,土了,,原来error_message_on这个轮子已经造好了。
貌似ActionView::Base.field_error_proc也很不错。

文档不是用来查的,平时阅读以下,知道有哪些方面的内容,不然真是书到用时方恨少
19 楼 Hooopo 2009-09-16  
amonlei 写道
很明显,楼主没有去阅读过 rails文档

文档都是用来查的.....
原来是error_message_on啊!
引用

error_message_on(object, method, *args)
Returns a string containing the error message attached to the method on the object if one exists. This error message is wrapped in a DIV tag, which can be extended to include a :prepend_text and/or :append_text (to properly explain the error), and a :css_class to style it accordingly. object should either be the name of an instance variable or the actual object. The method can be passed in either as a string or a symbol. As an example, let’s say you have a model @post that has an error message on the title attribute:

  <%= error_message_on "post", "title" %>
  # => <div class="formError">can't be empty</div>

  <%= error_message_on @post, :title %>
  # => <div class="formError">can't be empty</div>

  <%= error_message_on "post", "title",
      :prepend_text => "Title simply ",
      :append_text => " (or it won't work).",
      :css_class => "inputError" %>




<%= error_message_on "post", "title", 
      :prepend_text => "Title simply ", 
      :append_text => " (or it won't work).", 
      :css_class => "inputError" %> 

啊,土了,,原来error_message_on这个轮子已经造好了。
貌似ActionView::Base.field_error_proc也很不错。
18 楼 amonlei 2009-09-16  
<p>8.3 Customizing the Error Messages HTML<br><br>By default, form fields with errors are displayed enclosed by a div element with the fieldWithErrors CSS class. However, it’s possible to override that.<br><br>The way form fields with errors are treated is defined by ActionView::Base.field_error_proc. This is a Proc that receives two parameters:<br><br>    * A string with the HTML tag<br>    * An instance of ActionView::Helpers::InstanceTag.<br><br>Here is a simple example where we change the Rails behaviour to always display the error messages in front of each of the form fields with errors. The error messages will be enclosed by a span element with a validation-error CSS class. There will be no div element enclosing the input element, so we get rid of that red border around the text field. You can use the validation-error CSS class to style it anyway you want.<br>ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| if instance.error_message.kind_of?(Array) %(#{html_tag}&lt;span class="validation-error"&gt;&amp;nbsp; #{instance.error_message.join(',')}&lt;/span&gt;) else %(#{html_tag}&lt;span class="validation-error"&gt;&amp;nbsp; #{instance.error_message}&lt;/span&gt;) end end<br><br>This will result in something like the following:</p>
<p><img src="http://guides.rubyonrails.org/images/validation_error_messages.png" alt="" width="410" height="53"><br><br>Validation error messages</p>
<p> </p>
17 楼 amonlei 2009-09-16  
很明显,楼主没有去阅读过 rails文档
16 楼 whaosoft 2009-09-16  
yearl 写道
这样分离显示的界面更友好。

同意
15 楼 night_stalker 2009-09-16  
Hooopo 写道

不过你这个方案(I18N+error_message_on+一堆配置,貌似还有判断locale和在view里加t)有点杀鸡用牛刀的感觉了。。
大多数时候人家只是要一个可以正确显示中文的页面..


i18n 是 rails 2.2 才集成的。不用白不用。

没几个网站会有多语言显示的奇怪要求的 …… 不用在 view 判断 locale, 直接在 environment.rb 中设 zh-cn 就行了。
activerecord 默认载入 en-us.yml (可以在 activerecord 的目录里找到),不改 locale,直接把 en-us.yml 的内容替换掉会更高效和省内存(可以省 50k !……)
14 楼 one23 2009-09-16  
直接用QuakeWang的ActionView::Base.field_error_proc就可以省你很多了,我自己业余的应用用这个的
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  if instance.error_message.kind_of?(Array)
    %(#{html_tag}<span class="validation_error">&nbsp;  #{instance.error_message.first}</span>)
  else
    %(#{html_tag}<span class="validation_error">&nbsp;  #{instance.error_message}</span>)
  end
end

13 楼 Hooopo 2009-09-16  
night_stalker 写道
Hooopo 写道

这只是汉化,但是还没有解决我想把email域的错误信息放在email文本框右边或下面的需求,而且这个需求也是完全正当的...


啦啦啦:

<%= error_message_on @user, :email %>


如果出错就会产生:

<div class="formError">伊妹儿不能为空</div>

居然这样也行,学习了..

不过你这个方案(I18N+error_message_on+一堆配置,貌似还有判断locale和在view里加t)有点杀鸡用牛刀的感觉了。。
大多数时候人家只是要一个可以正确显示中文的页面..
12 楼 QuakeWang 2009-09-16  
JavaEye的做法是自定义field_error_proc,配合前端的js和css,能够在后台出错的时候和前段校验有一样的效果:
ActionView::Base.field_error_proc = Proc.new {|html_tag, instance|
  %(
  #{html_tag}
  <script type="text/javascript">
    var elm = $('#{instance.object_name}_#{instance.method_name}');
  elm.tooltip = new Tooltip(elm, {backgroundColor: "#FC9", borderColor: "#C96", textColor: "#000", textShadowColor: "#FFF"});
  elm.tooltip.content = "#{instance.error_message.kind_of?(Array) ? instance.error_message.join(',') : instance.error_message}"
  elm.addClassName('validation-failed');
  try{elm.focus();}catch(e){};
  </script>
  )
11 楼 Hooopo 2009-09-16  
yuan 写道
我的想法一直是这样的:我打算直接不理这个验证错误的提示,反正前端有js挡着,就不用费功夫去搞这些了。model验证我认为主要是保证数据的正确性,而js的验证则是为了用户体验。对于那种能想办法绕过前端验证的家伙,就无所谓什么用户体验了吧。对于用web却禁掉js的家伙直接不予支持。

我觉得没有什么问题,大家认为如何?

1.去不去搞和能不能搞是两个概念,当然这是针对那些说rails封装过度的人说的..
2.并不是所有禁用js的人都是要绕过你的js去做坏事,在浏览器里还有一个选项是“禁用js”之前,禁用js的用户就是合法用户。
3.有些设备不支持js,比如:
引用
JE改版后博客和圈子用了Ajax,貌似体验好了很多,但是我在用手机浏览的时候就无法回复。这一点《敏捷web开发》那本书做的就很好,在遇到不支持ajax的设备提供了普通的post方法,保证在所有设备上是可用的。
10 楼 night_stalker 2009-09-16  
Hooopo 写道

这只是汉化,但是还没有解决我想把email域的错误信息放在email文本框右边或下面的需求,而且这个需求也是完全正当的...


啦啦啦:

<%= error_message_on @user, :email %>


如果出错就会产生:

<div class="formError">伊妹儿不能为空</div>
9 楼 Hooopo 2009-09-16  
night_stalker 写道
貌似用 i18n 也可以定制 …… 而且更简单些:

environment.rb:
  config.i18n.default_locale = 'zh-cn'

2.给 ActiveRecord 加个中文 locale,控制错误消息的格式。

3.给 model 配置每个字段的翻译。

2 和 3 通过在 config/locales 里面添加 zh-cn.xxxxxx.yml 完成。最后输出的错误信息就是中文的并且合符格式的了。

居然修的这么快...
这只是汉化,但是还没有解决我想把email域的错误信息放在email文本框右边或下面的需求,而且这个需求也是完全正当的...
8 楼 night_stalker 2009-09-16  
- -,再添加这个:
zh-cn:
  users:
    name: 法号
    password: 芝麻开门

就显示为:

芝麻开门与确认值不匹配
法号已经被使用

不用每个字段都加 :message => ...
7 楼 yuan 2009-09-16  
我的想法一直是这样的:我打算直接不理这个验证错误的提示,反正前端有js挡着,就不用费功夫去搞这些了。model验证我认为主要是保证数据的正确性,而js的验证则是为了用户体验。对于那种能想办法绕过前端验证的家伙,就无所谓什么用户体验了吧。对于用web却禁掉js的家伙直接不予支持。

我觉得没有什么问题,大家认为如何?
6 楼 Hooopo 2009-09-16  
  activerecord:
    errors:
      template:
        header:
          one: "有 1 个错误发生导致「{{model}}」无法被保存。"
          other: "有 {{count}} 个错误发生导致「{{model}}」无法被保存。"
        body: "如下字段出现错误:"
      messages:
        inclusion: "不包含于列表中"
        exclusion: "是保留关键字"
        invalid: "是无效的"
        confirmation: "与确认值不匹配"
        accepted: "必须是可被接受的"
        empty: "不能留空"
        blank: "不能为空字符"
        too_long: "过长(最长为 {{count}} 个字符)"
        too_short: "過短(最短为 {{count}} 个字符)"
        wrong_length: "长度非法(必须为 {{count}} 个字符)"
        taken: "已经被使用"
        not_a_number: "不是数字"
        greater_than: "必须大于 {{count}}"
        greater_than_or_equal_to: "必须大于或等于 {{count}}"
        equal_to: "必须等于 {{count}}"
        less_than: "必须小于 {{count}}"
        less_than_or_equal_to: "必须小于或等于 {{count}}"
        odd: "必须为单数"
        even: "必须为双数"



哈哈,ns估计又没仔细看帖.......
这部分只是把默认的错误信息换成中文,但是会出现这样囧的错误提示:
引用

password与确认值不匹配
name已经被使用
...


这个只要在validation上面加:message选项就可以了
validates_presence_of :title, :message => "不能为空"

5 楼 night_stalker 2009-09-16  
Hooopo 写道
night_stalker 写道
貌似用 i18n 也可以定制 …… 而且更简单些

我只知道I18N可以把field名字国际化,但是如何使错误信息在页面布局可控还不知道怎么做


zh-cn.yml: 扔进 config/locales 里面
# Chinese (China) translations for Ruby on Rails
# by tsechingho (http://github.com/tsechingho)

...
...

  activerecord:
    errors:
      template:
        header:
          one: "有 1 个错误发生导致「{{model}}」无法被保存。"
          other: "有 {{count}} 个错误发生导致「{{model}}」无法被保存。"
        body: "如下字段出现错误:"
      messages:
        inclusion: "不包含于列表中"
        exclusion: "是保留关键字"
        invalid: "是无效的"
        confirmation: "与确认值不匹配"
        accepted: "必须是可被接受的"
        empty: "不能留空"
        blank: "不能为空字符"
        too_long: "过长(最长为 {{count}} 个字符)"
        too_short: "過短(最短为 {{count}} 个字符)"
        wrong_length: "长度非法(必须为 {{count}} 个字符)"
        taken: "已经被使用"
        not_a_number: "不是数字"
        greater_than: "必须大于 {{count}}"
        greater_than_or_equal_to: "必须大于或等于 {{count}}"
        equal_to: "必须等于 {{count}}"
        less_than: "必须小于 {{count}}"
        less_than_or_equal_to: "必须小于或等于 {{count}}"
        odd: "必须为单数"
        even: "必须为双数"
4 楼 Hooopo 2009-09-16  
night_stalker 写道
貌似用 i18n 也可以定制 …… 而且更简单些

我只知道I18N可以把field名字国际化,但是如何使错误信息在页面布局可控还不知道怎么做
3 楼 yearl 2009-09-16  
这样分离显示的界面更友好。

相关推荐

    rails 常见灵异错误汇总

    华为编程开发规范与案例提供了关于代码组织、命名规则、注释、错误处理等方面的指导,有助于创建更健壮、可维护的Rails应用。例如,遵循DRY(Don't Repeat Yourself)原则,避免代码重复;使用面向对象设计原则,如...

    关于rails 3.1 cucumber-rails 1.2.0

    这些支持文件增强了Cucumber-Rails的灵活性和可定制性。 结合Rails 3.1的Asset Pipeline和Cucumber-Rails 1.2.0,开发者能够构建出一个既高效又健壮的Web应用程序。Asset Pipeline优化了前端资源的处理,Cucumber-...

    Rails项目源代码

    Rails的核心理念是DRY(Don't Repeat Yourself),它鼓励开发者编写简洁、可复用的代码。框架提供了丰富的内置功能,如路由、ORM(对象关系映射)、数据库迁移和强大的脚手架工具,帮助快速开发应用程序。 2. **...

    rails api(文档)

    6. **错误处理**:Rails API鼓励返回标准的HTTP状态码和结构化的错误消息,以便客户端可以理解并适当地处理错误。 7. **JSON Schema**:通过使用JSON Schema,开发者可以定义API的数据结构和验证规则,增强API的可...

    Rails101_by_rails4.0

    《Rails101_by_rails4.0》是一本专注于Rails 4.0.0版本和Ruby 2.0.0版本的自学教程书籍,它定位于中文读者,旨在成为学习Rails框架的参考教材。Rails(Ruby on Rails)是一个采用Ruby语言编写的开源Web应用框架,它...

    使用Aptana+Rails开发Rails Web应用(中文)

    在开发Web应用时,Ruby on Rails(简称Rails)框架因其高效、简洁的代码风格和强大的社区支持而备受青睐。Aptana是一款强大的集成开发环境(IDE),尤其适用于Rails项目的开发,它提供了丰富的特性来提升开发效率。...

    The Rails 4 Way

    因此,通过学习Rails,读者不仅能掌握如何构建高效、可维护的Web应用,还能在Ruby编程方面得到显著提升。 #### 标签:rails、ruby 这两个标签指出了本书的主要关注点。**Rails**指的是Ruby on Rails框架,它是本书...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    ### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...

    rails4.0.0

    Rails 4增强了配置选项,允许开发者更灵活地定制Rails的行为,例如调整日志级别,设置默认时区等。 10. **测试与性能** Rails 4改进了测试框架,包括更好的测试覆盖率工具和更快的测试运行速度。同时,`active_...

    rails2-sample

    了解并正确运用MVC模式是构建高效、可维护的Rails应用的关键。 #### 6. Helpers, Forms, and Layouts(辅助方法、表单和布局) Rails提供了一系列辅助方法来简化HTML的生成和页面的布局。同时,表单是Web应用中不...

    rails指南 中文版

    Rails指南中文版是针对...此外,Rails社区活跃,有大量的插件和gem可供扩展,为开发者提供了丰富的资源和强大的支持。通过深入学习和实践,你将成为一名高效的Rails开发者,能够创建出优雅、高效且易于维护的Web应用。

    Rails上的API:使用Rails构建REST APIAPIs on Rails: Building REST APIs with Rails

    在本篇内容中,我们将深入探讨如何利用Ruby on Rails(简称Rails)这一强大的Web应用程序框架来构建可伸缩且易于维护的RESTful API。Rails以其简洁优雅的语法、高效的开发速度以及良好的社区支持而闻名,这使得它...

    Ruby on Rails安装指南(Ruby 1.8.6+Rails 2.0.2)

    Ruby on Rails 安装指南 Ruby on Rails 安装指南是指安装 Ruby 1.8.6 和 Rails 2.0.2 的详细步骤。首先,需要下载 Ruby One-Click Installer 版本,并安装 Ruby。然后,下载 Rails 2.0.2 版本,并安装。接下来,...

    rails-api-4.0.0

    在Rails 4.0.0中,引入了专门针对API开发的Rails API模式,为开发者提供了构建高效、可维护的RESTful API的工具。 一、Rails API模式的核心特点: 1. 轻量级:Rails API模式去掉了不必要的视图层,使得应用更加轻便...

    Rails

    标题 "Rails" 指的是 Ruby on Rails,一个开源的Web应用程序框架,它基于Ruby编程语言,遵循MVC(模型-视图-控制器)架构模式。Rails由David Heinemeier Hansson在2004年创建,其设计理念是强调代码的简洁性、DRY...

    [Rails] Crafting Rails Applications (英文版)

    [Pragmatic Bookshelf] Crafting Rails Applications Expert Practices for Everyday Rails Development (E-Book) ☆ 图书概要:☆ Rails 3 is a huge step forward. You can now easily extend the framework, ...

    Rails 101S

    - **深入实践CRUD功能**:详细讲解如何具体实现CRUD操作,包括数据验证、错误处理等高级特性。 - **MVC架构与RESTful概念**:介绍模型(Model)、视图(View)、控制器(Controller)三者之间的关系以及RESTful API的设计...

    rails 项目起步示例

    2. **bin**:存放可执行文件,如`rails`脚本,用于启动服务器、运行测试等。 3. **config**:配置文件的集合,包括数据库连接、路由设置、应用环境等。 4. **db**:数据库相关的文件,如迁移(migrations)用于...

    中文版rails教程

    Ruby的语法优雅,支持块、闭包和元编程,这使得Ruby在编写Rails应用时能够实现高度的灵活性和可扩展性。 **Rails框架核心组件** 1. **模型(Model)**:模型是应用的核心,负责处理数据和业务逻辑。ActiveRecord是...

Global site tag (gtag.js) - Google Analytics