number_to_human with currency - ruby-on-rails

I am using number_to_human to print 4 Million. I was wondering if there is a method that will add the $ to the front of the number?
I run into issues when I have a negative number.
If I just throw a $ in front I will get $-4 Million they want -$4 Million

It's builtin Rails:
number_to_currency(number_to_human(-4000000))
# => "-$4 Million"
The big advantage in using convention is that, when you need i18n, you just have to pass the locale:
number_to_currency(number_to_human(-4000000), locale: 'en-EU')
# => "-4 Million €"

Its interesting thing and If It would help to anybody:
How to Present thousands as "K", millions as "M" in ruby for that,
just follow the steps
Include NumberHelper in controller at top
include ActionView::Helpers::NumberHelper
Use this number_to_human Helper and pass the value, This will convert the value
<%= number_to_human(5223654) %>
Paste this code in en.yml to get it working
en:
number:
human:
decimal_units:
format: "%n%u"
units:
unit: ""
thousand: K
million: M
billion: B
trillion: T
quadrillion: Q

There must be better ways. however, here is a quick hack
amount = -4000000
if amount < 0
human = "-$#{number_to_human(amount.abs)}"
else
human = "$#{number_to_human(amount)}"
end
#apneadiving shows the real simple ways.

Related

Rails helper pass negative symbol as argument in self method

In my Rails 6, Ruby 2.7 app I'm using ActionView::Helpers::NumberHelper and number_to_currency method. Everything works fine but in one place I need to have negative amount instead of positive. To do so I created two methods:
formatters/document_amount_formatter.rb
module Formatters
# Formats the amount in a suitable form to be used in PDF creator.
class DocumentAmountFormatter
extend ActionView::Helpers::NumberHelper
# The method to call.
#
# #return [String]
def self.call(amount)
number_to_currency(amount.to_f, delimiter: '.', separator: ',', format: '%n €')
end
def self.negative_amount(amount)
number_to_currency(-amount.to_f, delimiter: '.', separator: ',', format: '%n €')
end
end
end
Both works well:
Formatters::CashbookDocumentAmountFormatter.call(cash_transactions.first.gross_amount)
=> "100,00 €"
Formatters::CashbookDocumentAmountFormatter.negative_amount(cash_transactions.first.gross_amount)
=> "-100,00 €"
But I'm not so sure if this is a good approach, tbh the code seems to be smelly. Is it possible to change those two methods into one? How to pass '-' or '+' as an argument inside of one of these methods?
Call call from within negative_amount.
def self.negative_amount(amount)
call(-amount)
end
The next question being, why have this method at all? The caller can write formatter.call(-amount) just as easily and more obviously.
Note that you probably shouldn't hard-code currency formatting and instead make use if internationalization.

Ruby/Rails - Converting an integer into a float excluding existing zeros

There must be a simple way to achieve this, I have an DB field containing an integer and I want to reformat it into a float to display.
As an integer my value looks like 6500 and I want it to display as 65.00
Within my model I have attempted to achieve this by creating the following method
def get_payment_amount_as_number
amount = self.payment_amount
return '%.02f' % self.payment_amount.to_f
end
Which results in the following being displayed: 6500.00
What would the best approach be to either strip the initial zeroes or to simply insert a decimal point?
Whilst I imagine this a ruby related question, I am not sure if rails has a handy helper already in place?
Thank you.
You could divide the number by 100:
payment_amount = 6595
'%.02f' % payment_amount.fdiv(100)
#=> "65.95"
'%.02f' % (payment_amount / 100.0)
#=> "65.95"
Or you could convert the number to a string and insert a decimal point:
payment_amount.to_s.rjust(3, '0').insert(-3, '.')
#=> "65.95"
Rails also provides several helpers to format numbers:
number_to_currency(65.95)
#=> "$65.95"
number_to_currency(1000)
#=> "$1,000.00"
And you might want to take a look at the money-rails gem which provides a mapping from cents to money objects.
You do this simply ...
def get_payment_amount_as_number
amount = self.payment_amount / 100
#to convert amount to float
amount.to_f
end
I find another one
amount = self.payment_amount
# => 6500
ans = '%.2f' % (amount/100)
# => "65.00"
int_value = 6500
float_value = float_value = '%.2f' % (int_value / 100.0)
puts int_value: int_value, float_value: float_value
it's all!

How to add decimal place to last two positions in string? Rails 4

I am trying to convert the string 1009 to become $10.09. I have been looking at the documentation for NumberHelpers for about 15 minutes now and am a bit surprised that I did not find any methods that can add a decimal point delimiter . before the last two positions of a string or integer.
At first, I tried:
number_to_currency("1009", :unit => "$")
# => $1,009.00
then I tried using:
number_to_currency("1009", :unit => "$", :precision => 0)
# => $1,009
which only removes digits after the decimal place, but does not shift the decimal place itself. As well, adding -2 as the precision argument throws ArgumentError.
I know this is possible to do with a few lines of JavaScript but I was looking for a more a pure Rails approach, if any.
How would someone be able to accomplish this?
You could just divide the number with 100. It's simple and it works. I guess you are converting cents to USD, I don't think there's any other way around it.
number_to_currency("1009".to_f / 100, :unit => "$")
You could also write a helper for this, something like...
def cents_to_usd(amount)
number_to_currency(amount.to_f / 100, :unit => "$")
end
So that it looks nicer in your views.

Ruby: Strip significant digits from number?

Suppose I have the number 1.29999. I want to just have 1.2 without the trailing 9s. Note, I don't want it to round to 1.3. How do I do this? I know there's the number helper, but I can't seem to get this working outside of a view. Any ideas?
For instance, number_with_precision 111.2345, :precision => 2 does not work if I just put it in a normal model function.
Thanks!
Another approach is to multiply by 100, truncate, then divide by 100.0:
$ irb --simple-prompt
>> (1.29999999*100).truncate/100.0
=> 1.29
Making it a method:
>> def truncate_to_two (x)
>> (x * 100).truncate/100.0
>> end
=> nil
>> truncate_to_two 6342.899
=> 6342.89
>> truncate_to_two -322.11892
=> -322.11
>> truncate_to_two 244.9342
=> 244.93
It's rudimentary, but you can do use string manipulation instead of math to do it. Example:
x = 1.29999
truncated = x.to_s.match(/(\d+\.\d{2})/)[0] # assumes the format "n.nn" with 2 or more digits of precision; the regex can be expanded to handle more cases
You can always include ActionView::Helpers::NumberHelper in your model to get access to the helpers.

Formatting a float to a minimum number of decimal places

I'm storing a decimal in rails and I need to have it display as a currency as such:
11.1230 => "$11.123"
11.1000 => "$11.10"
11.0100 => "$11.01"
11.1234 => "$11.1234"
Any easy way to do this?
def pad_number( number, min_decimals=2 )
s = "%g" % number
decimals = (s[/\.(\d+)/,1] || "").length
s << "." if decimals == 0
s << "0"*[0,min_decimals-decimals].max
end
puts [ 11.123, 11.1, 11.01, 11.1234, 11 ].map{ |n| pad_number(n) }
#=> 11.123
#=> 11.10
#=> 11.01
#=> 11.1234
#=> 11.00
Edit: Looks like this is Rails 3 specific, as Rails 2's number_with_precision method doesn't include the strip_insignificant_zeros option:
You can pass some options to number_to_currency (a standard Rails helper):
number_to_currency(11.1230, :precision => 10, :strip_insignificant_zeros => true)
# => "$11.123"
You need to provide a precision in order for the strip_insignificant_zeros option to work, though, otherwise the underlying number_with_precision method never gets called.
If you want to store as a float, you can use the number_to_currency(value) method in yours views for printing something that looks like $.
Correct me if I'm wrong (as I've rarely dealt with currency) but I think the conventional wisdom is to store dollar values as integers. That way you won't have to deal with funky float math.
So, convert it to three decimal fraction digits and then remove the final one if and only if it's a zero.
s.sub(/0$/, '')

Resources