Shopify/money

nonzero? does not return a boolean

Opened this issue · 5 comments

[6] pry(main)> Money.new(1, 'USD').nonzero?
=> 0.1e1
[7] pry(main)> Money.new(0, 'USD').nonzero?
=> nil

Looks like BigDecimal nonzero? doesn't return a Boolean but rather "Returns self if the value is non-zero, nil otherwise."

https://ruby-doc.org/stdlib-2.5.1/libdoc/bigdecimal/rdoc/BigDecimal.html#method-i-nonzero-3F

For comparison, Money.zero? does return a boolean.

[20] pry(main)> Money.new(0, 'USD').zero?
=> true
[21] pry(main)> Money.new(1, 'USD').zero?
=> false
[22] pry(main)> Money.new(-1, 'USD').zero?
=> false

I filed a bug against BigDecimal as well: ruby/bigdecimal#181

Quoting from ruby/bigdecimal#181 (comment)

This is the intentionally designed specification of Numeric#nonzero?.
See https://docs.ruby-lang.org/en/3.0.0/Numeric.html#method-i-nonzero-3F

It seems Money is not handling this correctly by delegating to BigDecimal and should override this method to return a Money.

Yeah either return a Money to remain consistent with BigDecimal's semantics, or I would expect nonzero? to really return a boolean -- but that was shot down in BigDecimal for some specific usage they anticipate (which I don't necessarily agree with, but don't have the influence to change either)