Ruby on rails 在Ruby on Rails中处理国际货币输入

Ruby on rails 在Ruby on Rails中处理国际货币输入,ruby-on-rails,internationalization,currency,Ruby On Rails,Internationalization,Currency,我有一个处理货币输入的软件。但是,如果您在美国,您可以输入一个数字作为12345.67;在法国,可能是12.345,67 在Rails中,是否有一种简单的方法使货币条目适应某个地区 请注意,我不是在寻找货币的显示(alanumber\u to\u currency),我是在寻找一个输入货币字符串并将其转换为十进制的人 您可以尝试将与委派类结合使用。我会这样做: class Product composed_of :balance, :class_name => "M

我有一个处理货币输入的软件。但是,如果您在美国,您可以输入一个数字作为
12345.67
;在法国,可能是
12.345,67

在Rails中,是否有一种简单的方法使货币条目适应某个地区

请注意,我不是在寻找货币的显示(ala
number\u to\u currency
),我是在寻找一个输入货币字符串并将其转换为十进制的人

您可以尝试将与委派类结合使用。我会这样做:

class Product
  composed_of :balance, 
         :class_name => "Money", 
         :mapping => %w(amount)
end

class Money < SimpleDelegator.new
   include Comparable
   attr_reader :amount

   def initialize(amount)
     @amount = Money.special_transform(amount)
     super(@amount)
   end

   def self.special_transform(amount)
     # your special convesion function here
   end

   def to_s
     nummber_to_currency @amount
   end
 end

优点是您不必修改控制器/视图上的任何内容。

使用内置的I18n应该允许您以一种格式(1234.56)输入价格,然后使用I18n将价格以
数字到货币
自动打印出来


当然,在筛选之前,您必须使用
设置
I18n.locale
,查看第2.3节。

您需要清理输入,以便用户可以键入几乎任何他们想要的内容,并且您将获得一致的内容存储在数据库中。假设您的模型名为“DoughEntry”,属性为“amount”,并将其存储为整数

下面是一个将字符串输入转换为美分的方法(如果字符串在delimeter后面以两位数结尾,则假定为美分)。您可能希望使其更智能,但概念如下:

def convert_to_cents(input)
  if input =~ /^.*[\.,]\d{2}$/ 
    input.gsub(/[^\d-]/,'').to_i
  else
    "#{input.gsub(/[^\d-]/,'')}00".to_i
  end
end

>> convert_to_cents "12,345"
=> 1234500
>> convert_to_cents "12.345,67"
=> 1234567
>> convert_to_cents "$12.345,67"
=> 1234567
然后覆盖默认的“金额”访问器,并通过该方法传递它:

class DoughEntry << ActiveRecord::Base

  def amount=(input)
    write_attribute(:amount, convert_to_cents(input))
  end

protected
  def convert_to_cents(input)
    if input =~ /^.*[\.,]\d{2}$/ 
      input.gsub(/[^\d-]/,'').to_i
    else
      "#{input.gsub(/[^\d-]/,'')}00".to_i
    end
  end
end

class DoughEntry您可以尝试一下:

   def string_to_float(string)

      string.gsub!(/[^\d.,]/,'')          # Replace all Currency Symbols, Letters and -- from the string

      if string =~ /^.*[\.,]\d{1}$/       # If string ends in a single digit (e.g. ,2)
        string = string + "0"             # make it ,20 in order for the result to be in "cents"
      end

      unless string =~ /^.*[\.,]\d{2}$/   # If does not end in ,00 / .00 then
        string = string + "00"            # add trailing 00 to turn it into cents
      end

      string.gsub!(/[\.,]/,'')            # Replace all (.) and (,) so the string result becomes in "cents"  
      string.to_f / 100                   # Let to_float do the rest
   end
以及测试用例:

describe Currency do
  it "should mix and match" do
    Currency.string_to_float("$ 1,000.50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,--").should eql(1000.to_f)
    Currency.string_to_float("$ 1,000.--").should eql(1000.to_f)    
  end     

  it "should strip the € sign" do
    Currency.string_to_float("€1").should eql(1.to_f)
  end

  it "should strip the $ sign" do
    Currency.string_to_float("$1").should eql(1.to_f)
  end

  it "should strip letter characters" do
    Currency.string_to_float("a123bc2").should eql(1232.to_f)
  end

  it "should strip - and --" do
    Currency.string_to_float("100,-").should eql(100.to_f)
    Currency.string_to_float("100,--").should eql(100.to_f)
  end

  it "should convert the , as delimitor to a ." do
    Currency.string_to_float("100,10").should eql(100.10)
  end

  it "should convert ignore , and . as separators" do
    Currency.string_to_float("1.000,10").should eql(1000.10)
    Currency.string_to_float("1,000.10").should eql(1000.10)
  end

  it "should be generous if you make a type in the last '0' digit" do
    Currency.string_to_float("123,2").should eql(123.2)
  end
我们写道:

class String
  def safe_parse
    self.gsub(I18n.t("number.currency.format.unit"), '').gsub(I18n.t("number.currency.format.delimiter"), '').gsub(I18n.t("number.currency.format.separator"), '.').to_f
  end
end

当然,在使用之前,您必须设置I18n.locale。它目前只将字符串转换为设置的区域设置的浮点值。(在我们的例子中,如果用户在法语网站上,我们希望货币金额文本仅包含与法语地区相关的符号和格式)。

您是否经常输入,以在键入数字时分隔分数??我从来没有,我没有,但我不能保证没有人会。我宁愿在用户的快乐方面犯错,而不是沮丧。此外,如果您正在复制在线银行对账单中的值,那么它可能已经被格式化为$and、and。小心,那些GSUB会去掉负号,所以如果你有负数,你会得到绝对值。
describe Currency do
  it "should mix and match" do
    Currency.string_to_float("$ 1,000.50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,50").should eql(1000.50)
    Currency.string_to_float("€ 1.000,--").should eql(1000.to_f)
    Currency.string_to_float("$ 1,000.--").should eql(1000.to_f)    
  end     

  it "should strip the € sign" do
    Currency.string_to_float("€1").should eql(1.to_f)
  end

  it "should strip the $ sign" do
    Currency.string_to_float("$1").should eql(1.to_f)
  end

  it "should strip letter characters" do
    Currency.string_to_float("a123bc2").should eql(1232.to_f)
  end

  it "should strip - and --" do
    Currency.string_to_float("100,-").should eql(100.to_f)
    Currency.string_to_float("100,--").should eql(100.to_f)
  end

  it "should convert the , as delimitor to a ." do
    Currency.string_to_float("100,10").should eql(100.10)
  end

  it "should convert ignore , and . as separators" do
    Currency.string_to_float("1.000,10").should eql(1000.10)
    Currency.string_to_float("1,000.10").should eql(1000.10)
  end

  it "should be generous if you make a type in the last '0' digit" do
    Currency.string_to_float("123,2").should eql(123.2)
  end
class String
  def safe_parse
    self.gsub(I18n.t("number.currency.format.unit"), '').gsub(I18n.t("number.currency.format.delimiter"), '').gsub(I18n.t("number.currency.format.separator"), '.').to_f
  end
end