🐷
ActiveSupport::Testing::TimeHelpersを使ってRailsの時間を固定した話
今日は、みてねコールドクターでエンジニアマネージャーをしている遠藤です。
前回までのお話
先日、たけむーが記事を投稿しました。
warekiとtimecopのgemの組み合わせでバグが発生していましたが、ActiveSupport::Testing::TimeHelpersを使用することで回避できました。
今回はその実装方法について説明します。
実装
普段はRSpecなどで使用することの多いActiveSupport::Testing::TimeHelpersですが、アプリケーション内でも使用できるように、以下のように実装しました。
config/initializers/timehelper.rb
if Rails.env.development? || Rails.env.staging?
require 'active_support/testing/time_helpers'
include ActiveSupport::Testing::TimeHelpers
end
内部での実装ですが、今回は既存のコードを改修する形で実装したため、concernを使用しました。
app/controllers/concerns/travel_time_concern.rb
module TravelTimeConcern
extend ActiveSupport::Concern
included do
helper_method :current_travel_time
before_action :enable_travel_time
after_action :disable_travel_time
end
def current_travel_time
# developでもstagingでもない場合は、current_travel_timeを返さない
return if !Rails.env.development? && !Rails.env.staging?
@current_travel_time ||= TravelTime.find_by(is_enable: true)
end
def enable_travel_time
if (Rails.env.development? || Rails.env.staging?) && current_travel_time.present?
travel_to(current_travel_time.travel_time)
end
end
def disable_travel_time
return if !Rails.env.development? && !Rails.env.staging?
travel_back
end
end
あとは、使用したいcontrollerにincludeするだけです。
app/controllers/xxx_controller.rb
class XxxController < ApplicationController
include TravelTimeConcern
end
本番に影響することを避けるため、Rails.envを多用してますね…
まとめ
TravelTimeはmodelで、DBに変更するための日付が保存されており、管理画面から変更できるようになっています。
このような実装にしたのは、PMや非エンジニアでも使用しやすくするためです。ただし、安全性やパフォーマンスを考慮する場合は、initializerなどに処理を書いて、環境変数で日時を設定する方がよいかもしれません。
QAや開発しやすくすることが好きなエンジニアを募集中です。
Discussion