When upgrading ruby from 1.8.7 to 1.9.3, if an empty string is specified in the argument of Time.parse, an exception will occur.
[EXCEPTION] ArgumentError: Occurs when date is given an empty string. Prior to 1.9.2, no exception was raised and an instance of Time representing the current time was returned.
Ruby 1.9.2 Reference Manual Time.parse
Since there were too many empty strings specified in Time.parse and it was difficult to fix, I decided to apply a monkey patch to Time.parse to solve it.
If an empty string is specified, Time.now is returned, and other than that, it is an override-like process that calls the parse method of the built-in class.
class Time
class << self
alias_method :__parse__, :parse
private :__parse__
def parse(time)
if time.empty?
#Returns the current time
Time.now
else
#Built-in class Time.Call parse
__parse__(time)
end
end
end
end
It is also possible to define it with self.parse.
class Time
class << self
alias_method :__parse__, :parse
private :__parse__
end
def self.parse(time)
if time.empty?
#Returns the current time
Time.now
else
#Built-in class Time.Call parse
__parse__(time)
end
end
end
I wanted to check the empty string while making use of the built-in class Time, so I thought that I should inherit Time and override it. However, when inheriting, you need to make the class name an alias and change all the places where Time.parse (arg) is used to the new class name. I gave up because this was the end of the story.
Next, I considered a monkey patch. Cookpad also supported monkey patches, so I referred to this. (It was written that you should not do it as much as possible.) How to apply monkey patches in Ruby on Rails applications
I prepared an extension class of Time and defined it as follows.
class Time
def self.parse(time)
if time.empty?
Time.now
else
Time.parse(time)
end
end
end
However, this is an error. This is also NG because the extension class Time.parse has been called all the time and it has become an infinite loop situation.
irb(main):002:0> Time.parse('2020-01-01 12:34:56')
SystemStackError: stack level too deep
from /usr/local/lib/ruby/1.9.1/irb/workspace.rb:80
Maybe IRB bug!
I investigated if there is a way to call the extension class Time.parse from the previous code and referred to the following article. Override existing method ](https://qiita.com/umanoda/items/33613b94ccabf7b1f851)
By using ʻalias_method and changing the method name of
parseof the extension class Time to
parse, it seemed that the infinite loop could be avoided. Just in case, it is defined as
private` so that it will not be called from the outside.
class Time
alias_method :__parse__, :parse
private :__parse__
def self.parse(time)
if time.empty?
Time.now
else
Time.parse(time)
end
end
end
Then I get an error if there is no parse
method.
alias_medhod could not be applied because parse is a class method.
bundle exec rails c
`alias_method': undefined method `parse' for class `Time' (NameError)
I have referred to the following about how to alias_method a class method. Add alias to class method
It could be applied by defining ʻalias_method` in class << self. The final form is here.
class Time
class << self
alias_method :__parse__, :parse
private :__parse__
end
def self.parse(time)
if time.empty?
Time.now
else
__parse__(time)
end
end
end
It is also possible to define the parse method in class << self as shown below. In that case, self is not necessary.
class Time
class << self
alias_method :__parse__, :parse
private :__parse__
def parse(time)
if time.empty?
Time.now
else
__parse__(time)
end
end
end
end
I think that there are few environments that use ruby 1.8.7 now, but I hope that it will be useful for upgrading the legacy code. Also, I think that it will be helpful for the method of monkey patch of the built-in class, so I hope it helps.
Ruby 1.9.2 Reference Manual Time.parse
How to apply monkey patches in Ruby on Rails applications
Override existing method ](https://qiita.com/umanoda/items/33613b94ccabf7b1f851)
Recommended Posts