Rails小数在API中作为字符串返回

时间:2018-11-18 01:08:14

标签: ruby-on-rails

我的数据库中有一个名为price的字段,它是一个十进制字段,在我的JSON API响应中,它作为字符串返回。

我想对字段进行一些验证,以使句点后最多2位数字,然后发现如果我使用小数字段,则可以在数据库级别应用精度。

t.decimal "price", precision: 10, scale: 2

然后我要计算服务对象中的总价:

services / statistics / monthly_rides_generator.rb

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

app / api / statistics / stats_api.rb

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?我该如何解决?

3 个答案:

答案 0 :(得分:2)

它作为字符串返回,因为ruby中的Decimal / BigDecimal是一个非常精确的数字。 Javascript / JSON没有像ruby的BigDecimal一样精确的数据类型。

如果打开控制台,则可以在浏览器中轻松看到以下内容: enter image description here

如果在序列化程序中将值转换为浮点数,则它将是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响应中的前端之前舍入该值即可。