Перестало работать десятичное сравнение Ruby on Rails - PullRequest
0 голосов
/ 06 января 2019

Я использовал объект состояния в базе данных, который отслеживает, какие начальные данные были загружены в него. Структура таблицы:

create_table "toolkit_states", force: :cascade do |t|
  t.boolean "signups", default: true
  t.decimal "database_version", precision: 5, scale: 2
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

Файл seed.rb проверяет версию базы данных и запускает блоки кода, а затем устанавливает базу данных версии после запуска блока. Работает нормально с версий 0.1 до 0.55.

Я добавил новый блок начальных данных. Для запуска этого блока проверяется database_version, и он должен быть 0,56. Следующее сравнение не работает:

if state.database_version == 0.56

По какой-то причине число 0,56 нельзя оценить на равенство со значением, хранящимся в базе данных. Он работал на всех значениях до 0,56.

Вот консольная сессия rails:

irb(main):001:0> state = ToolkitState.first
ToolkitState Load (0.4ms)  SELECT  "toolkit_states".* FROM "toolkit_states" ORDER BY "toolkit_states"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> #<ToolkitState id: 1, signups: false, database_version: 0.56e0, created_at: "2018-12-27 17:04:50", updated_at: "2018-12-27 17:04:56">
irb(main):002:0> state.database_version == 0.56
=> false
irb(main):003:0> state.database_version == 0.56e0
=> false
irb(main):004:0> state.database_version == 0.56.to_f
=> false
irb(main):005:0> state.database_version.to_f == 0.56
=> true

Когда я конвертирую значение с "to_f", сравнение работает. Моя проблема в том, что он работал без преобразования до значения 0,56

.

Ответы [ 2 ]

0 голосов
/ 07 января 2019
irb(main):001:0>  c = BigDecimal('0.56e0')
=> 0.56e0
irb(main):002:0> c == 0.56
=> false
irb(main):003:0>  c = BigDecimal('0.55e0')
=> 0.55e0
irb(main):004:0> c == 0.55
=> true

Работает для 0.55, а не для 0.56 Ошибка Rails?

0 голосов
/ 06 января 2019

Это происходит потому, что state.database_version является экземпляром класса BigDecimal . Эта статья объясняет, почему это BigDecimal.

Посмотрите на этот пример:

BigDecimal('0.56e0')
=> 0.56e0
irb(main):008:0> BigDecimal('0.56e0') == 0.56
=> false
irb(main):009:0> BigDecimal('0.56e0').to_f
=> 0.56

Как видите, 0.56e0 после преобразования в float тип становится равным 0,56, и ваше сравнение возвращает true.

Нейт более кратко объяснил, почему это происходит в этом комментарии .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...