Usando number_to_currency em modelos no Rails
Leia em 1 minuto
No PHP, uma função muito usada é number_format, mas no Ruby não temos nada assim nativamente. O Rails implementa sua própria versão com o helper number_to_currency, que satisfaz totalmente minhas necessidades. O problema é que ele só está disponível na view e, sendo assim, você não consegue utilizá-lo nem no modelo, nem no controller.
Para resolver isto, estendi algumas classes de modo que isso esteja disponível para qualquer instância de números (Fixnum, Bignum ou Float). Adicionalmente, um método to_number foi adicionado aos objetos da classe String, convertendo valores como 150.00 ou 150,00 para números do tipo Float.
module Currency
BRL = {:delimiter => ".", :separator => ",", :unit => "R$", :precision => 2, :position => "before"}
USD = {:delimiter => ',', :separator => ".", :unit => "US$", :precision => 2, :position => "before"}
DEFAULT = USD.merge(:unit => "$")
module String
def to_number(options={})
return self.gsub(/,/, '.').to_f if self.numeric?
nil
end
def numeric?
self =~ /^(|-)?[0-9]+((\.|,)[0-9]+)?$/ ? true : false
end
end
module Number
def to_currency(options = {})
number = self
default = Currency::DEFAULT.stringify_keys
options = default.merge(options.stringify_keys)
precision = options["precision"] || default["precision"]
unit = options["unit"] || default["unit"]
position = options["position"] || default["position"]
separator = precision > 0 ? options["separator"] || default["separator"] : ""
delimiter = options["delimiter"] || default["delimiter"]
begin
parts = number.with_precision(precision).split('.')
number = parts[0].to_i.with_delimiter(delimiter) + separator + parts[1].to_s
position == "before" ? unit + number : number + unit
rescue
number
end
end
def with_delimiter(delimiter=",", separator=".")
number = self
begin
parts = number.to_s.split(separator)
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\1#{delimiter}")
parts.join separator
rescue
self
end
end
def with_precision(precision=3)
number = self
"%01.#{precision}f" % number
end
end
end
class Fixnum; include Currency::Number; end
class Bignum; include Currency::Number; end
class Float; include Currency::Number; end
class String; include Currency::String; endPara ter estes novos métodos funcionando basta adicionar o código acima ao arquivo "environment.rb". Veja alguns exemplos de uso:
number = 9999.99
# using default settings
puts number.to_currency # $9,999.99
# using Brazilian Real
puts number.to_currency(Currency::BRL) # R$9.999,99
# using US Dollar
puts number.to_currency(Currency::USD) # US$9,999.99
# setting default to Brazilian Real
silence_warnings do
Currency::DEFAULT = Currency::BRL
end
# using default settings, now
# Brazilian Real
number.to_currency # R$9.999,99
puts '199.99'.to_number # 199.99
puts '199,99'.to_number # 199.99
puts '+199,99'.to_number # 199.99
puts '-199,99'.to_number # -199.99