如何配置 money-rails gem 以高于 4 位数字的精度工作
How to configure money-rails gem to work with higher precision than 4 digits
我们在应用程序中使用 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" = ... [["price_cents", "181.12"] ...]
有什么方法可以让 money-rails
gem 更精确地工作吗?似乎 Money 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
我们在应用程序中使用 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" = ... [["price_cents", "181.12"] ...]
有什么方法可以让 money-rails
gem 更精确地工作吗?似乎 Money 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