You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用Ruby Refinement自定义{now: Time.now}.inspect的输出?

如何让包含Time对象的Ruby集合输出可直接解析的代码格式?

需求是让Hash/Array的输出可以直接复制到代码中,通过Time.parse生成真实的Time实例。原代码仅对Time进行了Refinement,但调用Hash#inspect时输出的仍是Time的原生格式,无法满足需求。

解法一:使用pp替代inspect(推荐)

Ruby的pp(Pretty Print)是纯Ruby实现的打印工具,会遍历集合元素并调用其inspect方法,因此能触发Time的Refinement。只需保留Time的Refinement,改用pp输出即可:

# frozen_string_literal: true

module TimeMongoInspect
  refine Time do
    def inspect
      # 包含纳秒的格式,和期望输出匹配
      strftime("Time.parse('%Y-%m-%d %H:%M:%S.%N %z')")
    end
  end
end

using TimeMongoInspect

a = { time: Time.now }
pp a

输出示例:

{:time=>Time.parse('2023-08-29 00:39:08.546338569 +0000')}

这种方式无需修改Hash或Array的行为,代码简洁且符合Ruby的设计习惯。

解法二:Refine Hash和Array(若必须使用inspect)

如果一定要通过Hash#inspect和Array#inspect输出目标格式,需要重新实现这两个方法,确保它们调用元素的inspect(包括Refined的Time#inspect)。可以用更简洁的Ruby语法实现:

# frozen_string_literal: true

module TimeMongoInspect
  refine Time do
    def inspect
      "Time.parse('#{strftime('%Y-%m-%d %H:%M:%S.%N %z')}')"
    end
  end

  refine Hash do
    def inspect
      entries.map { |k, v| "#{k.inspect}=>#{v.inspect}" }
             .join(', ')
             .then { "{#{_1}}" }
    end
  end

  refine Array do
    def inspect
      map(&:inspect)
         .join(', ')
         .then { "[#{_1}]" }
    end
  end
end

using TimeMongoInspect

a = { time: Time.now }
puts a.inspect

为什么原方法不生效?

Ruby的核心集合类(Hash、Array)的原生inspect方法是用C实现的,不会调用Ruby层面的元素inspect方法,因此Time的Refinement无法被触发。只有重新实现集合类的inspect,或者使用纯Ruby实现的pp工具,才能让Refined的Time#inspect生效。

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 02:23:31