この記事は ビビッドガーデン Advent Calendar 2021 の11日目です。
自分はビビッドガーデンの社員さんじゃなくて、食べチョクの開発を週3日でお手伝いしているだけの人なのですけど、普通に記事も書かせてくれるし、この間は生産者さんの農場に行って出荷の様子を見せていただくことも出来ました。
こういう分け隔てないやり方が快適でもう一年以上お手伝いをしています。
travel_toの罠
さて、今日の話題は最近ハマったRailsの不具合について。
時刻に関わるテストをする時、timecopを使わなくても、Rails標準のTimeHelpersを使えばほぼ同等のことができるよ、というのは最近みんな知ってることになりつつあります。
食べチョクプロダクトチームでも、Timecop.travel("2020-12-14")
のようなコードをtravel_to("2020-12-14")
に置き換えるPRを出して一括置換しました。
ところが先日、置き換えたテストが通らなくなっていることに気づきました。CIで回している間は通っているのですが、自分の手元で走らせると落ちるのですよね。
travel_toには、travel_to("2018-01-02 15:00")
という具合に文字列を渡すと、その文字列をマシンのタイムゾーンでパースしちゃう(to_time使っちゃう)という不具合があり(参考)、修正のPRがマージされています。
ただこの修正、Rails6.1ではまだマージされてないのですよね。なので、USTで動かしている自分のマシンは見事この不具合にハマってしまいました。
パッチ
標準環境使えよという気持ちもあったのですけど、こういうタイムゾーンの不具合を甘く見ていると思わぬところで足元をすくわれるので、こういうのはちゃんとやっておきたい。一方で、CIとかみんなの環境では通ってるので、そんなに長い時間はかけてられない。
ということで、さくっとパッチを書きました。
# travel_to("2019-06-25") という具合に文字列を渡すと、RailsのTimezoneではなくPCのタイムゾーンでパースしてしまう不具合がある
# PRはすでにマージ済みだが 6.1時点でまだリリースされていないので、しばらくモンキーパッチを適用する
#
# https://github.com/rails/rails/pull/40694
# https://github.com/rails/rails/blob/6-1-stable/activesupport/lib/active_support/testing/time_helpers.rb#L157-L162
#
if ActiveSupport.version >= Gem::Version.new("6.2")
raise "モンキーパッチの削除を検討してください"
end
require "active_support/testing/time_helpers"
module TimeHelpersMonkeyPatch
def travel_to(date_or_time)
if date_or_time.is_a?(String)
super(Time.zone.parse(date_or_time))
else
super
end
end
end
if Rails.env.test?
ActiveSupport::Testing::TimeHelpers.prepend TimeHelpersMonkeyPatch
end
・travel_toに文字列が渡されたら、Time.zone.parseでパースしてからtravel_toを呼び直すようにする
・バージョンアップしたら外すように訴えて、不必要なパッチが残らないようにする
という感じの作りになっています。
まとめ
Rails標準のtravel_toの不具合に関する対応について書きました。
正直最初自信なかったのですけど、Rails詳しい人とか、Rubyコミッターとかハイスキルなエンジニアが増えたことで、これは間違いなく不具合だよね、パッチ書こうか、という感じで気軽に相談することが出来て、サクサクと片付けることが出来ました。
こういうのを相談できるチームっていいですよね。
ということで、そんなチームの一員になってみたい方を募集しております。
自分みたいに勤務日数を絞って業務委託で参画するやり方もあるし、正社員になってバリバリ働く働き方もあります。興味があればぜひコンタクトしてみてくださいませ。