Estou trabalhando em um sistema de carrinho de compras muito básico.
Eu tenho uma tabela items
que tem uma coluna price
do tipo integer
.
Estou com problemas para exibir o valor do preço em minhas visualizações para preços que incluem euros e centavos. Estou perdendo algo óbvio no que diz respeito à manipulação de moeda na estrutura Rails?
ruby-on-rails
ruby
currency
Barry Gallagher
fonte
fonte
DECIMAL(19, 4)
é uma escolha popular verificar isso também verificar aqui Formatos Mundo moeda para decidir quantos lugares para uso decimal, esperança ajuda.Respostas:
Você provavelmente desejará usar um
DECIMAL
tipo no seu banco de dados. Na sua migração, faça algo assim:No Rails, o
:decimal
tipo é retornado comoBigDecimal
, o que é ótimo para o cálculo de preços.Se você insistir em usar números inteiros, precisará converter manualmente de e para
BigDecimal
s em todos os lugares, o que provavelmente se tornará um problema.Conforme indicado pelo mcl, para imprimir o preço, use:
fonte
Aqui está uma abordagem simples e fina que utiliza
composed_of
(parte do ActiveRecord, usando o padrão ValueObject) e a jóia MoneyVocê precisará
Product
integer
coluna no seu modelo (e banco de dados), por exemplo:price
Escreva isso no seu
product.rb
arquivo:O que você obterá:
product.price = "$12.00"
converte automaticamente para a classe Moneyproduct.price.to_s
exibe um número no formato decimal ("1234.00")product.price.format
exibe uma string formatada corretamente para a moedaproduct.price.cents.to_s
fonte
composed_of
daqui, há mais detalhes sobre isso, além de uma implementação alternativa.A prática comum para lidar com moeda é usar o tipo decimal. Aqui está um exemplo simples de "Agile Web Development with Rails"
Isso permitirá que você lide com preços de -999.999,99 a 999.999,99.
Você também pode incluir uma validação em itens como
verificar sanidade seus valores.
fonte
Se você estiver usando o Postgres (e já que estamos em 2017 agora), convém
:money
tentar o tipo de coluna deles .fonte
Use jóia de trilhos de dinheiro . Ele lida muito bem com dinheiro e moedas no seu modelo e também tem um monte de ajudantes para formatar seus preços.
fonte
Apenas uma pequena atualização e uma coesão de todas as respostas para alguns aspirantes a juniores / iniciantes no desenvolvimento do RoR que certamente virão aqui para algumas explicações.
Trabalhando com dinheiro
Use
:decimal
para armazenar dinheiro no banco de dados, como o @molf sugeriu (e o que minha empresa usa como padrão-ouro ao trabalhar com dinheiro).Alguns pontos:
:decimal
será usado como oBigDecimal
que resolve muitos problemas.precision
escale
deve ser ajustado, dependendo do que você está representandoSe você trabalha com recebimento e envio de pagamentos
precision: 8
escale: 2
oferece999,999.99
o valor mais alto, o que é bom em 90% dos casos.Se você precisar representar o valor de uma propriedade ou carro raro, use um valor mais alto
precision
.Se você trabalha com coordenadas (longitude e latitude), certamente precisará de uma maior
scale
.Como gerar uma migração
Para gerar a migração com o conteúdo acima, execute no terminal:
ou
conforme explicado nesta postagem do blog .
Formatação de moeda
Dê um beijo de despedida nas bibliotecas extras e use ajudantes internos. Use
number_to_currency
como @molf e @facundofarias sugeridos.Para jogar com
number_to_currency
ajudante no console do Rails, enviar uma chamada para oActiveSupport
'sNumberHelper
classe, a fim de acessar o ajudante.Por exemplo:
dá a seguinte saída
Verifique o outro auxiliar
options
de number_to_currency .Onde colocá-lo
Você pode colocá-lo em um auxiliar de aplicativo e usá-lo dentro de visualizações para qualquer quantia.
Ou você pode colocá-lo no
Item
modelo como um método de instância e chamá-lo onde precisar formatar o preço (em visualizações ou auxiliares).E, um exemplo de como eu uso o
number_to_currency
controlador interno (observe anegative_format
opção usada para representar reembolsos)fonte
Usando Atributos Virtuais (Link para o Railscast revisado (pago)), você pode armazenar seus price_in_cents em uma coluna inteira e adicionar um atributo virtual price_in_dollars em seu modelo de produto como getter e setter.
Fonte: RailsCasts # 016: Atributos virtuais : os atributos virtuais são uma maneira limpa de adicionar campos de formulário que não são mapeados diretamente no banco de dados. Aqui eu mostro como lidar com validações, associações e muito mais.
fonte
Definitivamente inteiros .
E mesmo que o BigDecimal exista tecnicamente,
1.5
você ainda terá um Float puro em Ruby.fonte
Se alguém estiver usando o Sequel, a migração será semelhante a:
de alguma maneira Sequel ignora: precisão e: escala
(Versão da sequela: sequela (3.39.0, 3.38.0))
fonte
Minhas APIs subjacentes estavam usando centavos para representar dinheiro, e eu não queria mudar isso. Também não estava trabalhando com grandes quantias de dinheiro. Então, eu apenas coloquei isso em um método auxiliar:
Isso converte o número inteiro em uma string com pelo menos três dígitos (adicionando zeros à esquerda, se necessário) e, em seguida, insere um ponto decimal antes dos dois últimos dígitos, nunca usando a
Float
. A partir daí, você pode adicionar quaisquer símbolos monetários adequados ao seu caso de uso.É definitivamente rápido e sujo, mas às vezes tudo bem!
fonte
Estou usando desta maneira:
É claro que o símbolo da moeda, a precisão, o formato etc. dependem de cada moeda.
fonte
Você pode passar algumas opções para
number_to_currency
(um auxiliar de exibição padrão do Rails 4):Como postado por Dylan Markow
fonte
Código simples para Ruby & Rails
fonte