After years of working with ruby, I finally came across a good need for ruby refinement!
# 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
The desired output is
{:time=>Time.parse('2023-08-29 00:39:08.546338569 +0000')}
In case someone is curious, I want to be able to cut-n-paste output into code, however, I need the date to be properly interpetted as a real Time class..
ChatGPT said to also refine Array and Hash
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
However, I thought this was making the problem even more complicated and was the wrong way to go.
What is the correct way to do this?
The issue is that refinements are lexically scoped.
Meaning they apply only to code you write in the same script.
If you refine
Time#inspect. Every call toTime#inspectfrom the same file/script will use your refined method.If you call
Time.now.inspectdirectly you will see that.However, the refinement has no effect on code not in your script. For example
Hash#inspectis not defined in your code. It's defined elsewhere that does not have your refinement. Therefore anyTime#inspectcalled from there does not use your refinement.Your options:
Hash#inspectand if you wantArray#inspectin your refinement and live with the complexity.Time#inspectglobally without refinements and live with the side-effects.