Ruby number_to_currency显示完全错误的数字!

时间:2010-04-08 02:32:21

标签: ruby-on-rails ruby

问候!我是一个老式的Delphi程序员,通常可以实现Mac,Ruby,Rails和Web编程的飞跃。我已于本月底报名参加Advanced Rails研讨会。与此同时,我一直致力于将任务关键(当然)应用程序从Delphi移植到RAILS。感觉就像我过去一年的大部分时间都把我的头埋在书本或播客中。

现在,我遇到了一个重大问题,我正在撕扯我的头发。我真的不知道该去哪里,我拼命地想要部署这个bug,我感觉有点疯狂。 (该公司数据库目前正在一个古老的XP盒子上运行,当天看起来比较生气。)

因此,我建立了一个显示问题的测试数据库。我正在跑步:

 OS/X 10.6.3
 Rails 2.3.5
 ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0]
 MySQL 5.1.38-log via socket
 MySQL Client Version 5.1.8

ActiveRecord::Schema.define(:version => 20100406222528) do

     create_table “money”, :force => true do |t|
     t.decimal “amount_due”, :precision => 10, :scale => 2, :default => 0.0
     t.decimal “balance”, :precision => 10, :scale => 2, :default => 0.0
     t.text “memofield”
     t.datetime “created_at”
     t.datetime “updated_at”
     end

索引视图就在生成器之外,稍加修改以添加打破我的格式。

Listing money
<table>

     <tr>
     <th>Amount</th>
     <th>Amount to_s </th>
     <th>Balance to $</th>
     <th>Balance with_precision </th>
     <th>Memofield</th>
     </tr>

<% @money.each do |money| %>

     <tr>
     <td><%=h money.amount_due %></td>
     <td><%=h money.amount_due.to_s(‘F’) %></td>
     <td><%=h number_to_currency(money.balance) %></td>
     <td><%=h number_with_precision(money.balance, :precision => 2) %></td>
     <td><%=h money.memofield %></td>
     <td><%= link_to ‘Show’, money %></td>
     <td><%= link_to ‘Edit’, edit_money_path(money) %></td>
     <td><%= link_to ‘Destroy’, money, :confirm => ‘Are you sure?’, :method => :delete %></td>
     </tr> *<% end %> *</table>

<%= link_to ‘New money’, new_money_path %>

这看起来效果很好。然后我开始使用生产数据进行测试,并遇到了number_to_currency的主要问题。

数据库中的数字是:10542.28,我用MySQL查询浏览器验证了它。 RAILS会将此显示为10542.28 除非我调用number_to_currency,然后该数字显示为:$ 15422.80

错误似乎发生在10,000.00和10,999.99之间的任何数字。到目前为止,我还没有看到它超出该范围,但我显然没有测试过所有内容。

我想我的解决方法是删除number_to_currency,但这会使视图看起来非常草率和不专业。格式混乱,事情没有正确对齐,我不能强制显示到小数点后两位。

我非常希望有一个简单的解决方案。我无法想象这是一个普遍存在的问题。它会影响这么多人,有人会修复它!但我不知道从哪里开始。

我非常想要一些帮助。

(稍后 - number_with_precision以与number_to_currency相同的方式失败。)

苏·彼得森

8 个答案:

答案 0 :(得分:3)

在找到修复程序之前,您可以自行创建:)

def formatted_number(n)
  a,b = sprintf("%0.2f", n).split('.')
  a.gsub!(/(\d)(?=(\d{3})+(?!\d))/, '\\1,')
  "$#{a}.#{b}"
end

DATA.each do |n|
  puts formatted_number(n)
end

__END__
1
1.1
1.11
11
11.1
11.11
111
111.1
111.11
1111
1111.1
1111.11
11111
11111.1
11111.11
111111
111111.1
111111.11
1111111
1111111.1
1111111.11
11111111
11111111.1
11111111.11
111111111
111111111.1
111111111.11

输出

$1.00
$1.10
$1.11
$11.00
$11.10
$11.11
$111.00
$111.10
$111.11
$1,111.00
$1,111.10
$1,111.11
$11,111.00
$11,111.10
$11,111.11
$111,111.00
$111,111.10
$111,111.11
$1111,111.00
$1111,111.10
$1111,111.11
$1,1111,111.00
$1,1111,111.10
$1,1111,111.11
$11,1111,111.00
$11,1111,111.10
$11,1111,111.11

答案 1 :(得分:2)

可能与此相关:

rails number_to_currency bug?

答案 2 :(得分:1)

class Float
  def to_currency
    a,b = sprintf("%0.2f", self).split('.')
    a.gsub!(/(\d)(?=(\d{3})+(?!\d))/, '\\1,')
    "$#{a}.#{b}"
  end
end

class Integer
  def to_currency
    a,b = sprintf("%0.2f", self).split('.')
    a.gsub!(/(\d)(?=(\d{3})+(?!\d))/, '\\1,')
    "$#{a}.#{b}"
  end
end

x = [100.236, 2, 123456789.1]
x.each do | n |
  puts x.to_currency
end

# Results
# $100.24
# $2.00
# $123,456,789.10

我在Float和Integer类中添加了to_currency方法。它将数字作为格式化字符串返回。

答案 3 :(得分:0)

另一个(更有趣的)解决方案可能会帮助您解决错误

def formatted_number(n, options={})
  options = {
    :precision => 2,
    :separator => '.',
    :delimiter => ',',
    :format => "$%s"
  }.merge(options)

  a,b = sprintf("%0.#{options[:precision]}f", n).split('.')
  a.gsub!(/(\d)(?=(\d{3})+(?!\d))/, "\\1#{options[:delimiter]}")
  sprintf(options[:format], "#{a}#{options[:separator]}#{b}")
end

DATA.each do |n|
  # default $1,234.56
  puts formatted_number(n)

  # precise $0.12345
  puts formatted_number(n, :precision => 5)

  # European 1.234,56 EUR
  puts formatted_number(n, :separator => ',', :delimiter => '.', :format => '%s EUR')

  # line break
  puts ''
end

__END__
5.5966
52.5344
3021.565
34809.48
25923.68342

输出

$5.60
$5.59660
5,60 EUR

$52.53
$52.53440
52,53 EUR

$3,021.57
$3,021.56500
3.021,57 EUR

$34,809.48
$34,809.48000
34.809,48 EUR

$25,923.68
$25,923.68342
25.923,68 EUR

答案 4 :(得分:0)

@smotchkkiss我尝试了两个建议。他们都在我的系统上做了与number_to_currency相同的事情。我怀疑这是我正在运行的Ruby版本中的内容。

我花了大部分时间试图在我的系统上安装更新版本的Ruby,最后放弃并从Time Machine完成了一个完整的系统还原。我还在学习Mac的怪癖,我真的设法弄乱了我的RubyGems安装。

@Andrew Grimm我很乐意留下这个评论。我认为没办法这样做(运行Snow Leopard,Firefox w NoScript)。我花了至少30分钟通过常见问题解答,试图找到一种方式来发表评论而不是回答。不行。

答案 5 :(得分:0)

这个的答案,至少是部分答案。

我设法加载了更新版本的Ruby(ruby 1.8.7(2010-01-10 patchlevel 249)),问题就消失了。这显然是Ruby中的一个错误。现在我只需要弄清楚如何在MacBook上安装一个较新版本的Ruby系统,以及我用作测试服务器的2分钟。

答案 6 :(得分:0)

我遇到了同样的问题。似乎问题在于将大十进制转换为浮点数。我在formatted_number方法中更改了一行,并且能够得到应该出现的数字:

a,b = sprintf("%0.#{options[:precision]}f", n).split('.')

更改为:

a,b = sprintf("%0.#{options[:precision]}f", n.to_s.to_f).split('.')

首先转换为字符串,然后转换为浮点数。这很好,但在基础问题得到解决之前,它将对我们有用。

答案 7 :(得分:0)

我最终在我的所有Mac上加载了rvm gem,现在我正在运行ruby 1.8.7 p249。这解决了我的问题。

我确实验证了Ruby中的错误,我发现了更多信息:

http://www.ruby-forum.com/topic/189053#827091

cihaks - 听起来他们建议的临时补丁非常类似于你正在做的事情。无论如何,感谢帖子和信息。 : - )