如何格式化Rails编辑字段中显示的值?

时间:2009-02-26 18:59:27

标签: ruby-on-rails ruby forms

我想让编辑表单字段尽可能方便用户使用。例如,对于数值,我希望该字段以逗号显示(如number_with_precision)。

这在显示器方面很容易,但是编辑呢?有没有办法做到这一点?

我正在使用Rails FormBuilder。经过调查,我发现它使用InstanceTag,它使用<attribute>_value_before_type_cast获取字段的值,这意味着不会调用覆盖<attribute>

6 个答案:

答案 0 :(得分:38)

到目前为止,我提出的最好的是这样的:

<%= f.text_field :my_attribute, :value => number_with_precision(f.object.my_attribute) %>

my_attribute可以返回格式化的值,如下所示:

def my_attribute
  ApplicationController.helpers.number_with_precision(read_attribute(:my_attribute))
end

但你仍然需要使用:value

<%= f.text_field :my_attribute, :value => f.object.my_attribute %>

这似乎做了很多工作。

答案 1 :(得分:9)

我更喜欢你的第一个答案,格式化在视图中完成。但是,如果要在模型中执行格式化,可以对getter和setter使用包装器方法,并避免完全使用:value选项。

你最终会得到这样的东西。

def my_attribute_string
  foo_formatter(myattribute)
end

def my_attribute_string=(s)
  # Parse "s" or do whatever you need to with it, then set your real attribute.
end

<%= f.text_field :my_attribute_string %>

Railscasts在episode #32的text_field中用Time对象覆盖了它。其中非常聪明的部分是它们如何处理验证错误。仅凭这一点值得关注这一集。

答案 2 :(得分:4)

这是一个老问题,但如果有人遇到这个问题,你可以使用number_to_X助手。它们具有您显示编辑值所需的所有属性:

<%= f.text_field :my_number, :value => number_to_human(f.object.my_number, :separator => '', :unit => '', :delimiter => '', :precision => 0) %>

还有更多可用的属性:http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html

答案 3 :(得分:3)

如果您希望在编辑期间创建或维护格式,则需要添加Javascript以实现“掩码”。 Here is a demo.

这是these results中的第一次点击。

答案 4 :(得分:3)

您可以使用number_format插件。通过为模型中的现有数字属性指定number_format,该属性现在将在所有表单和视图中显示为Rails格式。在插入数据库之前,它还将从该格式(通过表单分配时)进行解析。 (该插件还创建了纯粹的数字unformatted_<attribute-name>访问器,可以继续用于算术,或者直接进行数字分配或检索,以实现无缝集成。)

class MyModel < ActiveRecord::Base
  # this model has the balance attribute, which we
  #  want to display using formatting in views,
  #  although it is stored as a numeric in the database
  number_format :balance, 
                :precision => 2,
                :delimiter => ',',
                :strip_trailing_zeros => false

  def increment_balance
    unformatted_balance += 10
  end

您还可以将上述内容与Javascript解决方案结合使用,这可以强制用户在编辑时保持小数点和数千个分隔符,尽管这不是必需的。

答案 5 :(得分:1)

我做了类似的事情。我们使用自定义表单构建器格式化时间和长度。它使用现有的text_field,但包装它以便可以自定义值:

class SuperFormBuilder < ActionView::Helpers::FormBuilder
  include ApplicationHelper
  include FormHelper
  include ActionView::Helpers::TagHelper
  include ActionView::Helpers::FormTagHelper

  def length_field(label,*args)
    scale = 'medium'
    args.each do |v|
      if v.has_key?(:scale)
        scale = v[:scale]
        v.delete(:scale)
      end
    end
  value = length_conversion(@object.send(label.to_sym),scale)
  options = (args.length > 0) ? args.pop : {}
  return has_error(label, text_field_tag(field_name(label),value,*args) + ' ' +  length_unit(scale))
end

private
def field_name(label)
  return @object_name + "[#{label}]"
end

def has_error(label, output)
  return    "<div class='fieldWithErrors'>#{output}</div>" if @object.errors[label]
  return output
end

它的用法如下:

<%= form_for( @section, {:action => 'save', :id => @section.id}, :builder => SuperFormBuilder) do |sf| %> 
   <%= sf.length_field :feed_size_min_w, :size => 3, :scale => 'small'  %>
<% end %>

最终结果是基于他们在系统上选择的适当单位中的值(公制,英制)和缩小IE小=英寸或毫米。

我基本上从现有的表单构建器中复制了text_field方法,该构建器使用text_field_tag本身。

有两个问题:1)了解对象字段的名称以及如何访问对象以获取要格式化的值。 2)获得正确的名称,以便在提交表单时,它是正确的参数散列的一部分。

表单构建器被赋予一个类变量@object。您可以使用.send方法获取字段的值。在我的情况下,我将标签:feed_size_min_w发送到@object并返回其长度。然后我将其转换为我想要的格式,并将其提供给text_field_tag。

字段的名称是让它以params哈希结束的关键,在我的例子中是params [:sections]。我做了一个名为field_name的辅助函数来处理这个问题。

如果该标签上有错误,则has_error将字段包装在错误div中。