Module: ConcernsOnRails::Support::Money
- Defined in:
- lib/concerns_on_rails/support/money.rb
Overview
Formats an integer subunit amount (e.g. cents) as a human-readable money string. Pure and stateless; used by Models::Monetizable. Uses BigDecimal throughout so there is no binary-float rounding drift.
Class Method Summary collapse
-
.delimit(integer_string, delimiter) ⇒ Object
Insert the thousands delimiter into a non-negative integer string.
-
.format(cents, options = {}) ⇒ Object
format(199999) => “$1,999.99” format(-500, unit: “£”) => “-£5.00” format(1234, unit: “¥”, precision: 0, subunit_to_unit: 1) => “¥1,234”.
Class Method Details
.delimit(integer_string, delimiter) ⇒ Object
Insert the thousands delimiter into a non-negative integer string.
33 34 35 |
# File 'lib/concerns_on_rails/support/money.rb', line 33 def delimit(integer_string, delimiter) integer_string.reverse.gsub(/(\d{3})(?=\d)/, "\\1#{delimiter}").reverse end |
.format(cents, options = {}) ⇒ Object
format(199999) => “$1,999.99” format(-500, unit: “£”) => “-£5.00” format(1234, unit: “¥”, precision: 0, subunit_to_unit: 1) => “¥1,234”
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/concerns_on_rails/support/money.rb', line 14 def format(cents, = {}) unit = .fetch(:unit, "$") precision = .fetch(:precision, 2) delimiter = .fetch(:delimiter, ",") separator = .fetch(:separator, ".") subunit = .fetch(:subunit_to_unit, 100) decimal = BigDecimal(cents.to_s) / subunit # BigDecimal#round returns an Integer for precision <= 0, so re-wrap it # in a BigDecimal before #to_s("F") (Integer#to_s would read "F" as a radix). rounded = BigDecimal(decimal.abs.round(precision).to_s) whole, _, frac = rounded.to_s("F").partition(".") whole = delimit(whole, delimiter) number = precision.positive? ? "#{whole}#{separator}#{frac.ljust(precision, '0')[0, precision]}" : whole "#{'-' if decimal.negative?}#{unit}#{number}" end |