Сериализация хэша с датами в виде рельсов YAML
TL; DR: Rails 5.1, Ruby 2.4.0 сериализует хэш, включающий объекты Time с кавычками вокруг строкового представления времени. Этих цитат не было в Rails 2.3, Ruby 1.8.7 и они ломали мое приложение; как мне от них избавиться?
Контекст и детали
Я обновляю приложение с Rails 2.3, Ruby 1.8.7 до Rails 5.1, Ruby 2.4.0. у меня есть ReportService
класс, который имеет report_params
аргумент конструктора, который принимает хеш. После создания этих объектов этот хэш сериализуется в формате YAML.
class ReportService < ApplicationRecord
# irrelevant AR associations omitted
serialize :report_params
serialize :output_urls
end
Пользователь отправляет форму, содержащую детали отчета, который он хочет запустить, включая строку, которая анализируется с помощью Time.parse(), которая передается в качестве аргумента конструктора; таким образом, код (в процедурной форме для удаления ненужных деталей, с большим количеством посторонних вещей пропущен) выглядит так
offset = customer.timezone.nil? ? '+0000' : customer.timezone.formatted_offset(:time => start_date)
params[:date_from] = Time.parse("#{start_date} #{params[:hour_from]}:{params[:min_from]} #{offset}").utc.strftime('%Y-%m-%d %H:%M:%S')
report_args = {...
report_params: { ...
date: params[:date_from]
}
}
ReportService.create(report_args)
Когда я смотрю в моей базе данных MYSQL, я обнаруживаю, что мое поле report_params выглядит ... date_from: '2017-12-27 00:00:00' ...
, Соответствующий код в старой версии дает результат, который выглядит следующим образом ... date_from: 2017-12-27 00:00:00 ...
, Это плохо, потому что YAML в этом поле анализируется (устаревшим) Java-приложением, которое опрашивает базу данных, чтобы проверить наличие новых записей, и кавычки, кажется, нарушают эту десериализацию (бросая java.lang.Exception: BaseProperties.getdate()
); если я вручную отредактирую поле, чтобы удалить кавычки, приложение будет работать как положено. Как я могу предотвратить добавление этих кавычек?
1 ответ
Rails5.1/Ruby2.4 делают это правильно, так как 2017-12-27 00:00:00
не является допустимым значением yaml.
Хорошая вещь serialize
принимает два параметра, второй является классом сериализатора.
Итак, все, что вам нужно сделать, это:
class ReportService < ApplicationRecord
# irrelevant AR associations omitted
serialize :report_params, MyYaml
serialize :output_urls, MyYaml
end
и реализовать MyYaml
, делегируя все, кроме date
/ time
в YAML
и производить все, что вам нужно для них.
Вышесказанное действительно для любого формата сериализованных данных, оно полностью не зависит от формата. Примеры.