2.3.4 :017 > "9.12".to_f * 100
=> 911.9999999999999
rails g scaffold product name price_cents:integer
class Product < ApplicationRecord
# 数据库存储价格字段是 price_cents,整形,单位为分
def price
(price_cents || 0) / 100.0
end
def price=(v)
# 这里用.round就是为了解决上面的911.99999999问题
self.price_cents = (v.to_f * 100).round
end
end
app/controllers/products_controller.rb
def product_params
params.require(:product).permit(:name, :price)
end
app/views/products/_form.html.erb
<div class="field">
<%= form.label :price %>
<%= form.text_field :price, id: :product_price %>
</div>
app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
class << self
def price_attr(model_attr, db_attr="#{model_attr}_cents")
class_eval <<-CODE, __FILE__, __LINE__ + 1
def #{model_attr}
(#{db_attr} || 0) / 100.0
end
def #{model_attr}=(v)
self.#{db_attr} = (v.to_f * 100).round
end
CODE
end
end
end
class Product < ApplicationRecord
price_attr :price
end
require 'money'
# 10.00 USD
money = Money.new(1000, "USD")
money.cents #=> 1000
money.currency #=> Currency.new("USD")
# Comparisons
Money.new(1000, "USD") == Money.new(1000, "USD") #=> true
Money.new(1000, "USD") == Money.new(100, "USD") #=> false
Money.new(1000, "USD") == Money.new(1000, "EUR") #=> false
Money.new(1000, "USD") != Money.new(1000, "EUR") #=> true
# Arithmetic
Money.new(1000, "USD") + Money.new(500, "USD") == Money.new(1500, "USD")
Money.new(1000, "USD") - Money.new(200, "USD") == Money.new(800, "USD")
Money.new(1000, "USD") / 5 == Money.new(200, "USD")
Money.new(1000, "USD") * 5 == Money.new(5000, "USD")
# Unit to subunit conversions
Money.from_amount(5, "USD") == Money.new(500, "USD") # 5 USD
Money.from_amount(5, "JPY") == Money.new(5, "JPY") # 5 JPY
Money.from_amount(5, "TND") == Money.new(5000, "TND") # 5 TND
# Currency conversions
some_code_to_setup_exchange_rates
Money.new(1000, "USD").exchange_to("EUR") == Money.new(some_value, "EUR")
# Formatting (see Formatting section for more options)
Money.new(100, "USD").format #=> "$1.00"
Money.new(100, "GBP").format #=> "£1.00"
Money.new(100, "EUR").format #=> "€1.00"