Rails десятичный возвращается как строка в API - PullRequest
0 голосов
/ 18 ноября 2018

У меня есть поле с именем price в моей базе данных, которое является десятичным полем, и в моем ответе API JSON оно возвращается в виде строки.

Я хотел применить некоторые проверки к полю, которые позволили бы максимум 2цифры после точки и выяснилось, что если я использую десятичное поле, я могу применить точность на уровне БД.

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

Затем я хочу рассчитать общую стоимость в объекте обслуживания:

services / statistics / month_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"
}

Я хочу, чтобы это поле было возвращено в том виде, в котором оно было сохранено, поскольку мне нужно, чтобы во внешнем интерфейсе мне было необходимо использовать число с плавающей запятой / десятичное число для выполнения других вычислений.

Почему оно возвращает строку, когдаэто десятичное поле?Как я могу это исправить?

Ответы [ 3 ]

0 голосов
/ 18 ноября 2018

Возвращается в виде строки, потому что Decimal / BigDecimal в ruby ​​- очень точное число.Javascript / JSON не имеет типа данных, который был бы таким же точным, как BigDecimal в ruby.

Вы можете легко увидеть это в своем браузере, если откроете консоль: enter image description here

Если вы преобразуете значение в число с плавающей точкой в ​​вашем сериализаторе, тогда это будет число с плавающей точкой в ​​объекте JSON, которое возвращается вашим API, но вы должны быть осторожны с тем, как ваши клиенты используют эти данные.Если они не используют библиотеку, которая может обрабатывать точность, то вы будете получать ошибки округления и часто будете тратить свои деньги на копейки.

Я использовал библиотеку decimal.js для вещейкак это, и это работает отлично.https://github.com/MikeMcl/decimal.js/

0 голосов
/ 19 ноября 2018

Я решил решить эту проблему, изменив тип столбца на Float, переименовав его в price_cents, добавив money-rails и монетизировав столбец. Затем я просто вызываю to_f или округляем значение прямо перед отображением или отправляю его клиенту в ответе API.

0 голосов
/ 18 ноября 2018

Одним из способов решения этой проблемы является приведение его к нужному типу в сериализаторе:

# 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...