为什么postgreSQL将十进制字段存储为BigDecimal哈希?

时间:2012-02-28 22:09:48

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

我在rails3 / postgreSQL中有以下模型/表:

create_table "admin_reports", :force => true do |t|
  t.string   "report"
  t.decimal  "result"
  t.string   "result_type"
  t.datetime "created_at"
  t.datetime "updated_at"
end

在生产时,AdminReports.result不存储小数,而是存储哈希:

AdminReport.last

=> #<AdminReport id: 4, report: "dau", result: #<BigDecimal:cbca0f0,'0.8E1',4(8)>, result_type: "percentage", created_at: "2012-02-28 22:05:15", updated_at: "2012-02-28 22:05:15">

我希望看到的地方:

AdminReport.last

=> #<AdminReport id: 4, report: "dau", result: 10.10, result_type: "percentage", created_at: "2012-02-28 22:05:15", updated_at: "2012-02-28 22:05:15">

在rails控制台中,即使我尝试手动设置结果字段,如下所示:

@a = AdminReport.last
@a.result = 8.89
@a.save

它仍然将AdminReport.result显示为BigDecimal哈希。任何想法在这里发生了什么?

由于

1 个答案:

答案 0 :(得分:6)

您使用的是十进制列:

create_table "admin_reports", :force => true do |t|
  #...
  t.decimal  "result"
  #...
end

这通常意味着您要使用固定数量的小数位,因此您可能还想指定:precision:scale选项。当ActiveRecord看到一个十进制列时,它会将值转换为Ruby的BigDecimal,以便在Ruby-land中保持所需的小数位数;如果AR使用浮点值,那么你会遇到所有常见的浮点问题,你可能最终将一个值从数据库中拉出来并将另一个值放回而不是故意改变它,使用BigDecimal完全避免了这个问题。

当你看到这个:

#<BigDecimal:cbca0f0,'0.8E1',4(8)>

您刚刚看到BigDecimal的标准inspect输出。如果您使用to_s(或"#{...}"),您会看到更熟悉的内容。

所以没有什么可担心的。如果您需要使用非整数运算但不想要浮点的所有问题,那么十进制列(:precision:scale)是正确的选择。