Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add formatting for EUR locales #1231

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ def period_label(period)

def format_money(number_or_money, options = {})
money = Money.new(number_or_money)
options.reverse_merge!(money.default_format_options)
options.reverse_merge!(money.format_options(I18n.locale))
number_to_currency(money.amount, options)
end

def format_money_without_symbol(number_or_money, options = {})
money = Money.new(number_or_money)
options.reverse_merge!(money.default_format_options)
options.reverse_merge!(money.format_options(I18n.locale))
ActiveSupport::NumberHelper.number_to_delimited(money.amount.round(options[:precision] || 0), { delimiter: options[:delimiter], separator: options[:separator] })
end

Expand Down
35 changes: 1 addition & 34 deletions lib/money.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class Money
include Comparable, Arithmetic
include Comparable, Arithmetic, Formatting
include ActiveModel::Validations

class ConversionError < StandardError
Expand Down Expand Up @@ -54,29 +54,6 @@ def exchange_to(other_currency, date: Date.current, fallback_rate: nil)
end
end

def cents_str(precision = currency.default_precision)
format_str = "%.#{precision}f"
amount_str = format_str % amount
parts = amount_str.split(currency.separator)

if parts.length < 2
""
else
parts.last.ljust(precision, "0")
end
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

legacy, not being used anywhere


# Use `format` for basic formatting only.
# Use the Rails number_to_currency helper for more advanced formatting.
def format
whole_part, fractional_part = sprintf("%.#{currency.default_precision}f", amount).split(".")
whole_with_delimiters = whole_part.chars.to_a.reverse.each_slice(3).map(&:join).join(currency.delimiter).reverse
formatted_amount = "#{whole_with_delimiters}#{currency.separator}#{fractional_part}"

currency.default_format.gsub("%n", formatted_amount).gsub("%u", currency.symbol)
end
alias_method :to_s, :format

def as_json
{ amount: amount, currency: currency.iso_code }.as_json
end
Expand All @@ -97,16 +74,6 @@ def <=>(other)
end
end

def default_format_options
{
unit: currency.symbol,
precision: currency.default_precision,
delimiter: currency.delimiter,
separator: currency.separator,
format: currency.default_format
}
end

private
def source_must_be_of_known_type
unless @source.is_a?(Money) || @source.is_a?(Numeric) || @source.is_a?(BigDecimal)
Expand Down
35 changes: 35 additions & 0 deletions lib/money/formatting.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Money::Formatting
# Fallback formatting. For advanced formatting, use Rails number_to_currency helper.
def format
whole_part, fractional_part = sprintf("%.#{currency.default_precision}f", amount).split(".")
whole_with_delimiters = whole_part.chars.to_a.reverse.each_slice(3).map(&:join).join(currency.delimiter).reverse
formatted_amount = "#{whole_with_delimiters}#{currency.separator}#{fractional_part}"

currency.default_format.gsub("%n", formatted_amount).gsub("%u", currency.symbol)
end
alias_method :to_s, :format

def format_options(locale = nil)
local_option_overrides = locale_options(locale)

{
unit: currency.symbol,
precision: currency.default_precision,
delimiter: currency.delimiter,
separator: currency.separator,
format: currency.default_format
}.merge(local_option_overrides)
end

private
def locale_options(locale)
case [ currency.iso_code, locale.to_sym ]
when [ "EUR", :nl ], [ "EUR", :pt ]
{ delimiter: ".", separator: ",", format: "%u %n" }
when [ "EUR", :en ], [ "EUR", :en_IE ]
{ delimiter: ",", separator: "." }
else
{}
end
end
end
4 changes: 2 additions & 2 deletions test/helpers/application_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def setup

test "#totals_by_currency(collection: collection, money_method: money_method)" do
assert_equal "$3.00", totals_by_currency(collection: [ @account1, @account2 ], money_method: :balance_money)
assert_equal "$3.00 | -€7,00", totals_by_currency(collection: [ @account1, @account2, @account3 ], money_method: :balance_money)
assert_equal "$3.00 | -€7.00", totals_by_currency(collection: [ @account1, @account2, @account3 ], money_method: :balance_money)
assert_equal "", totals_by_currency(collection: [], money_method: :balance_money)
assert_equal "$0.00", totals_by_currency(collection: [ Account.new(currency: "USD", balance: 0) ], money_method: :balance_money)
assert_equal "-$3.00 | €7,00", totals_by_currency(collection: [ @account1, @account2, @account3 ], money_method: :balance_money, negate: true)
assert_equal "-$3.00 | €7.00", totals_by_currency(collection: [ @account1, @account2, @account3 ], money_method: :balance_money, negate: true)
end
end
19 changes: 0 additions & 19 deletions test/lib/money/currency_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,6 @@ class Money::CurrencyTest < ActiveSupport::TestCase
assert_equal 2, @currency.default_precision
end

test "can extract cents string from amount" do
value1 = Money.new(100)
value2 = Money.new(100.1)
value3 = Money.new(100.12)
value4 = Money.new(100.123)
value5 = Money.new(200, :jpy)

assert_equal "00", value1.cents_str
assert_equal "10", value2.cents_str
assert_equal "12", value3.cents_str
assert_equal "12", value4.cents_str
assert_equal "", value5.cents_str

assert_equal "", value4.cents_str(0)
assert_equal "1", value4.cents_str(1)
assert_equal "12", value4.cents_str(2)
assert_equal "123", value4.cents_str(3)
end

test "step returns the smallest value of the currency" do
assert_equal 0.01, @currency.step
end
Expand Down
4 changes: 2 additions & 2 deletions test/lib/money_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ class MoneyTest < ActiveSupport::TestCase
end

test "can cast to string with basic formatting" do
assert_equal "$1,000.90", Money.new(1000.899).format
assert_equal "€1.000,12", Money.new(1000.12, :eur).format
assert_equal "$1,000.90", Money.new(1000.899).to_s
assert_equal "€1.000,12", Money.new(1000.12, :eur).to_s
end

test "converts currency when rate available" do
Expand Down