我正在开发一个非常基本的购物车系统。

我有一个表items,它的列价格类型为整型。

我在视图中显示包含欧元和美分的价格时遇到了麻烦。在Rails框架中处理货币时,我是否遗漏了一些明显的东西?


当前回答

Ruby和Rails的简单代码

<%= number_to_currency(1234567890.50) %>

OUT PUT => $1,234,567,890.50

其他回答

使用Virtual Attributes(链接到修订的(付费)Railscast),您可以将price_in_cents存储在一个整数列中,并在您的产品模型中添加虚拟属性price_in_dollars作为getter和setter。

# 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

来源:RailsCasts #016:虚拟属性:虚拟属性是添加不直接映射到数据库的表单字段的一种干净的方式。在这里,我将展示如何处理验证、关联等。

Ruby和Rails的简单代码

<%= number_to_currency(1234567890.50) %>

OUT PUT => $1,234,567,890.50

使用金钱轨道宝石。它在你的模型中很好地处理金钱和货币,也有一堆帮助来格式化你的价格。

只是对RoR开发中一些有抱负的初级/初学者的所有答案进行了一点更新和整合,这些答案肯定会在这里得到一些解释。

与金钱打交道

使用:decimal在DB中存储货币,就像@molf建议的那样(也是我的公司在处理货币时使用的黄金标准)。

# 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

几个点:

:decimal is going to be used as BigDecimal which solves a lot of issues. precision and scale should be adjusted, depending on what you are representing If you work with receiving and sending payments, precision: 8 and scale: 2 gives you 999,999.99 as the highest amount, which is fine in 90% of cases. If you need to represent the value of a property or a rare car, you should use a higher precision. If you work with coordinates (longitude and latitude), you will surely need a higher scale.

如何生成迁移

要生成带有上述内容的迁移,在terminal中运行:

bin/rails g migration AddPriceToItems price:decimal{8-2}

or

bin/rails g migration AddPriceToItems 'price:decimal{5,2}'

正如这篇博客文章所解释的。

货币格式

和额外的库说再见,使用内置的helper。请按照@molf和@facundofarias的建议使用number_to_currency。

要在Rails控制台中使用number_to_currency助手,请向ActiveSupport的NumberHelper类发送一个调用,以便访问这个助手。

例如:

ActiveSupport::NumberHelper.number_to_currency(2_500_000.61, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")

给出以下输出

2500000,61€

检查number_to_currency助手的其他选项。

放在哪里

您可以将它放在应用程序助手中,并在视图中任意使用它。

module ApplicationHelper    
  def format_currency(amount)
    number_to_currency(amount, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

或者,您可以将它作为实例方法放在Item模型中,并在需要格式化价格的地方(在视图或helper中)调用它。

class Item < ActiveRecord::Base
  def format_price
    number_to_currency(price, unit: '€', precision: 2, separator: ',', delimiter: '', format: "%n%u")
  end
end

并且,我如何在控制器内使用number_to_currency的示例(注意negative_format选项,用于表示退款)

def refund_information
  amount_formatted = 
    ActionController::Base.helpers.number_to_currency(@refund.amount, negative_format: '(%u%n)')
  {
    # ...
    amount_formatted: amount_formatted,
    # ...
  }
end

如果你正在使用Postgres(因为我们现在已经是2017年了),你可能想尝试一下他们的:money列。

add_column :products, :price, :money, default: 0