# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, precision: 8, scale: 2
# Add a price_in_cents integer column
$ rails g migration add_price_in_cents_to_products price_in_cents:integer
# Use virtual attributes in your Product model
# app/models/product.rb
def price_in_dollars
price_in_cents.to_d/100 if price_in_cents
end
def price_in_dollars=(dollars)
self.price_in_cents = dollars.to_d*100 if dollars.present?
end
# precision is the total number of digits
# scale is the number of digits to the right of the decimal point
add_column :items, :price, :decimal, :precision => 8, :scale => 2
13 回答
使用money-rails gem . 它可以很好地处理您的模型中的货币和货币,还有一堆帮助器来格式化您的价格 .
如果你正在使用Postgres(因为我们现在是2017年),你可能想尝试一下他们的
:money
列类型 .这是一个很好的,简单的方法,利用
composed_of
(ActiveRecord的一部分,使用ValueObject模式)和Money gem你需要
Money gem(版本4.1.0)
一个模型,例如
Product
模型(和数据库)中的
integer
列,例如:price
在
product.rb
文件中写下:你会得到什么:
如果没有任何额外的更改,您的所有表单都将显示美元和美分,但内部表示仍然只是美分 . 表单将接受"$12,034.95"之类的值并将其转换为您 . 无需在模型中添加额外的处理程序或属性,也无需在视图中添加帮助程序 .
product.price = "$12.00"
自动转换为Money类product.price.to_s
显示十进制格式的数字("1234.00")product.price.format
显示货币的格式正确的字符串如果您需要发送美分(到需要便士的支付网关),
product.price.cents.to_s
货币兑换免费
Simple code for Ruby & Rails
对RoR开发中的一些有抱负的初级/初学者的所有答案进行一点点更新和凝聚,这肯定会在这里得到一些解释 .
用钱工作
使用
:decimal
在DB中存储资金,正如@molf建议的那样(以及我的公司在使用资金时用作金标准) .几点:
:decimal
将被用作BigDecimal
,它解决了很多问题 .应根据您所代表的内容调整
precision
和scale
如果您使用收款和发送付款,
precision: 8
和scale: 2
会给您999,999.99
作为最高金额,这在90%的情况下都没有问题 .如果您需要代表房产或稀有汽车的 Value ,您应该使用更高的
precision
.如果您使用坐标(经度和纬度),您肯定需要更高的
scale
.如何生成迁移
要使用上述内容生成迁移,请在终端中运行:
要么
正如blog中所解释的那样 .
货币格式
KISS额外的库再见并使用内置助手 . 使用
number_to_currency
作为@molf和@facundofarias建议 .要在Rails控制台中使用
number_to_currency
帮助程序,请调用ActiveSupport
的NumberHelper
类以访问帮助程序 .例如:
给出以下输出
检查number_to_currency帮助者的另一个
options
.把它放在哪里
您可以将它放在应用程序帮助程序中,并在视图中使用它以获取任何数量 .
或者您可以将它作为实例方法放在
Item
模型中,并在需要格式化价格的地方(在视图或帮助程序中)调用它 .并且,我在一个控制器内使用
number_to_currency
的示例(注意negative_format
选项,用于表示退款)处理货币的常用做法是使用十进制类型 . 以下是“使用Rails进行敏捷Web开发”的简单示例
这将允许您处理从-999,999.99到999,999.99的价格
您可能还希望在项目中包含验证
理智 - 检查你的 Value 观 .
绝对是integers .
即使BigDecimal在技术上存在,
1.5
仍会在Ruby中为您提供纯粹的Float .如果有人使用续集,迁移将看起来像:
不知怎的,Sequel忽略了:精度和:规模
(续集版本:续集(3.39.0,3.38.0))
我这样使用它:
当然,货币符号,精度,格式等取决于每种货币 .
我的底层API都使用美分代表金钱,我不想改变它 . 我也不是在处理大笔资金 . 所以我把它放在一个辅助方法中:
将整数转换为至少包含三位数的字符串(必要时添加前导零),然后在最后两位数之前插入一个小数点,从不使用
Float
. 从那里,您可以添加适合您的用例的任何货币符号 .这绝对是快速和肮脏的,但有时候这很好!
使用Virtual Attributes (Link to revised(paid) Railscast),您可以将price_in_cents存储在整数列中,并在产品中添加虚拟属性price_in_dollars模型作为吸气剂和二传手 .
来源:RailsCasts #016: Virtual Attributes:虚拟属性是添加不直接映射到数据库的表单字段的简洁方法 . 在这里,我将展示如何处理验证,关联等 .
您可以将一些选项传递给
number_to_currency
(标准的Rails 4视图助手):由Dylan Markow发布
您可能希望在数据库中使用
DECIMAL
类型 . 在迁移中,执行以下操作:在Rails中,
:decimal
类型返回BigDecimal
,这非常适合价格计算 .如果你坚持使用整数,你将不得不手动转换到
BigDecimal
的所有地方,这可能只是一个痛苦 .正如mcl所指出的,要打印价格,请使用: