Techioz Blog

改良を使用して { now: Time.now }.inspect の出力をカスタマイズするように変更するにはどうすればよいですか?

概要

何年も Ruby を扱ってきた結果、ついに Ruby を改良する必要性が十分にあることに気づきました。

# frozen_string_literal: true

module TimeMongoInspect
  refine Time do

    def inspect
      strftime("Time.parse('%Y-%m-%d %H:%M:%S %z')")
    end

    def to_s
      strftime("Time.parse('%Y-%m-%d %H:%M:%S %z')")
    end
  end
end

using TimeMongoInspect

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

望ましい出力は

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

興味がある人のために付け加えておきますが、出力をコードにカットアンドペーストできるようにしたいのですが、日付がリアルタイム クラスとして適切に解釈される必要があります。

ChatGPTは配列とハッシュも改良すると言われています

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

    def to_s
      inspect
    end
  end
  
  refine Hash do
    def inspect
      "{" + self.map { |k, v| "#{k.inspect}: #{v.inspect}" }.join(", ") + "}"
    end
  end

  refine Array do
    def inspect
      "[" + self.map { |v| v.inspect }.join(", ") + "]"
    end
  end
end

しかし、これでは問題がさらに複雑になり、間違った方法だと思いました。

これを行う正しい方法は何ですか?

解決策

問題は、改良が語彙的にスコープされることです。

つまり、同じスクリプト内で作成したコードにのみ適用されます。

Time#inspectを絞り込むと。同じファイル/スクリプトから Time#inspect を呼び出すたびに、洗練されたメソッドが使用されます。

Time.now.inspect を直接呼び出すと、それが表示されます。

ただし、この改良は、スクリプトに含まれていないコードには影響しません。たとえば、Hash#inspect がコード内で定義されていません。これは、あなたの洗練されていない他の場所で定義されています。したがって、そこから呼び出される Time#inspect は、あなたの調整を使用しません。

オプション: