ruby-on-rails - 如何配置钱轨 gem 以高于 4 位数字的精度工作

标签 ruby-on-rails ruby currency money-rails

我们在应用程序中使用 money-rails gem。到目前为止,我们可以使用 4 位十进制数字精度,但我们需要切换到 6 位。不幸的是,我无法将更高精度的数字存储到 Postgres 中 - 数字在保存之前会进行四舍五入。

class MyModel < ApplicationRecord
  monetize :price_cents # :price_cents, :decimal, default: 0, precision: 30, scale: 10
end

货币本身似乎可以在更高的精度下正常工作

pry(main)> Money.new(181.123456789).to_f
=> 1.81123456789

在控制台中测试模型。保存之前一切正常。

my_model = MyModel.find(1)
my_model.price = Money.new(181.123456789)
my_model.price.to_f # => 1.81123456789
my_model.save
my_model.price.to_f # => 1.8112

ActiveRecord 输出表示修剪后的数字实际上正在发送到数据库。 (注意 181.12)。

UPDATE "my_models" SET "price_cents" = $1 ... [["price_cents", "181.12"] ...]

有什么方法可以让money-rails gem 更精确地工作吗?看来金钱 gem 本身精度更高是没有问题的。

最佳答案

这种行为来自于资金四舍五入,要关闭它,请使用:

Money.infinite_precision = true

这是测试:

require "bundler/inline"

gemfile(ENV['INSTALL']=='1') do
  source "https://rubygems.org"
  gem "rails", '~>6.0'
  gem "sqlite3"
  gem 'money-rails'
end

require "minitest/autorun"
require "logger"
require "active_record"
require 'money-rails'

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
  create_table(:models, force: true){|t| t.decimal :price_cents, default: 0, precision: 30, scale: 10 }
end

# to remove config warnings:
Money.locale_backend = :currency
Money.default_currency= :usd

# actual fix:
Money.infinite_precision = true

MoneyRails::Hooks.init # in a normal app is called automatically


class Model < ActiveRecord::Base
  monetize :price_cents 
end

class BugTest < Minitest::Test
  def test_association_stuff
    m = Model.create!(price_cents: 181.123456789).reload
    assert_equal 181.123456789, m.price_cents
    assert_equal 1.81123456789, m.price.to_f

    m2 = Model.create(price: Money.new(182.123456789)).reload
    assert_equal 1.82123456789, m2.price.to_f
  end
end

关于ruby-on-rails - 如何配置钱轨 gem 以高于 4 位数字的精度工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60671933/

相关文章:

sql - 将钱存储在小数列中 - 什么精度和比例?

ruby-on-rails - ActiveRecord::Associations::集合到数组

ruby-on-rails - Errno::ENOENT: 没有这样的文件或目录@rb_sysopen log/production.log (heroku deploy)

javascript - Rails - 单击事件 - 如何处理 2 个 Ruby 方法之间的竞争条件?

ruby - 从二进制文件中解析 Unix 时间戳

ruby - UTC 时间重置为 2000-01-01( ruby )。如何防止时间重置?

ruby-on-rails - 将 Ruby 字符串插值作为 ID

Ruby Enumerable#count 算法中的性能问题

ItemTemplate 中的 .Net String.Format 货币与数据绑定(bind)中的小计

java - 获取没有 Locale 常量的国家/地区的货币格式