我的数据库中有一个名为price的字段,它是一个十进制字段,在我的JSON API响应中,它作为字符串返回。
我想对字段进行一些验证,以使句点后最多2位数字,然后发现如果我使用小数字段,则可以在数据库级别应用精度。
t.decimal "price", precision: 10, scale: 2
然后我要计算服务对象中的总价:
class CurrentMonthRidesGenerator
def initialize(current_user)
@current_user = current_user
end
def call
user_current_month_rides_by_day.map do |date, rides_on_day|
{
day: formatted_date(date),
total_distance: total_distance(rides_on_day),
avg_ride: avg_ride(rides_on_day),
avg_price: avg_price(rides_on_day),
total_price: total_price(rides_on_day)
}
end
end
...
def total_price(rides)
rides.map(&:price).sum
end
end
get '/current_month' do
Statistics::CurrentMonthRidesGenerator.new(current_user).call
end
但是在API响应中,该字段是一个字符串。
{
"day": "November, 8th",
"total_distance": "9km",
"avg_ride": "9km",
"avg_price": "100.0PLN",
"total_price": "100.0"
}
我希望将此字段保存后返回,因为我需要在前端使用浮点数/十进制数来进行其他计算。
为什么它是十进制字段时为什么返回String?我该如何解决?
答案 0 :(得分:2)
它作为字符串返回,因为ruby中的Decimal / BigDecimal是一个非常精确的数字。 Javascript / JSON没有像ruby的BigDecimal一样精确的数据类型。
如果在序列化程序中将值转换为浮点数,则它将是API返回的JSON对象中的浮点数,但您要注意客户端如何使用此数据。如果他们不使用可以处理精度的库,那么您将得到舍入误差,并且经常在计算上花费一分钱。
我一直在使用decimal.js库来处理类似的事情,并且效果很好。 https://github.com/MikeMcl/decimal.js/
答案 1 :(得分:0)
解决此问题的一种方法是将其转换为序列化器中所需的类型:
# app/serializers/your_model_serializer.rb
class YourModelSerializer < ActiveModel::Serializer
attributes :day,
:total_distance,
:avg_ride,
:avg_price,
:total_price
def total_price
object.total_price.to_f
end
end
答案 2 :(得分:0)
我决定通过将列类型更改为Float
,将其重命名为price_cents
,添加money-rails
并通过该列货币化来解决此问题。然后,我只需调用to_f
或在显示值或将其发送到API响应中的前端之前舍入该值即可。