【问题标题】:Serialise hash with dates as YAML rails将带有日期的哈希序列化为 YAML 轨道
【发布时间】:2018-01-02 16:43:16
【问题描述】:

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 应用程序解析,该应用程序轮询数据库以检查新条目,并且引号似乎破坏了反序列化(抛出 @ 987654327@);如果我手动编辑该字段以删除引号,则该应用程序将按预期工作。如何防止添加这些引号?

【问题讨论】:

    标签: ruby-on-rails ruby serialization rails-upgrade


    【解决方案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,并为他们生产您需要的任何东西。

    以上内容适用于任何格式的序列化数据,它完全与格式无关。 Examples.

    【讨论】:

    • 感谢您的回复,但我将序列化为 YAML,而不是 JSON。因为旧版 java 应用程序正在解析 yaml,所以我需要保留输出格式。
    • 您可以根据需要进行序列化,只需实现序列化程序本身即可。
    • 我现在明白了,谢谢。然而,根据yamllint.com,新旧输出都是有效的 YAML。另外,奇怪的是,如果我在哈希上应用 .to_yaml 方法,那么 Time 对象的表示中没有引号。例如2.4.0 :004 &gt; ds = Time.now().to_s =&gt; "2018-01-02 15:39:26 +0000" 2.4.0 :005 &gt; time = Time.parse(ds) =&gt; 2018-01-02 15:39:26 +0000 #similarly, date = DateTime.parse(ds) 2.4.0 :009 &gt; {date: date, time: time}.to_yaml =&gt; "---\n:date: !ruby/object:DateTime 2018-01-02 15:39:26.000000000 Z\n:time: 2018-01-02 15:39:26.000000000 +00:00\n
    • 抱歉,不允许我再编辑该评论以使其更具可读性!
    • 我认为新的 Rails 行为保留了序列化和反序列化的类,所以它是因为 strftime() time 方法添加了引号。你的方法应该允许我解决这个问题,所以接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 2023-01-20
    • 2013-11-28
    • 2013-06-25
    相关资源
    最近更新 更多