LoginSignup
7
6

More than 5 years have passed since last update.

created_atがTimeクラスになる現象

Posted at

モデルのtimestamp(created_at,updated_at)は通常、TimeWithZoneクラスのインスタンスですが、これがTimeクラスになる現象が発生しました。
Timeクラスになるとどうなるかと言うと、railsが時刻を扱う際には通常、DBにはUTCで格納し、入出力時にTimeZoneを加えるようになっていますが、これが行われないのでUTCのまま扱われ、viewにも当然UTCで出力されるようになります。

原因

せっかちな人のために結論を書くと、利用していた論理削除gemrails4_acts_as_paranoidが原因でした。
これをparanoiaに置き換えたところ解決しました。
以下、原因を調べた方法について書きます。

調査

まず、timestampがTimeWithZoneを返す正常なrailsアプリを用意し、DBを比較してみたところ、DBには差がないことが分かりました。
つまりActiveRecordがTimeZoneを付加するところをスキップしているということです。
というわけでActiveRecordのソースを見ます。
timestamp.rbの先頭のコメントに以下のような記述があります。

timestamp.rb
  # If your attributes are time zone aware and you desire to skip time zone conversion to the current Time.zone
  # when reading certain attributes then you can do following:
  #
  #   class Topic < ActiveRecord::Base
  #     self.skip_time_zone_conversion_for_attributes = [:written_on]
  #   end

どうやら意図せずskip_time_zone_conversion_for_attributesを定義してしまっていたようです。
プロダクトコードを検索しましたが定義している様子はないので、gemのソースを検索してみると、rails4_acts_as_paranoidのソースを発見しました。

rails4_acts_as_paranoid.rb
def self.extended(base)
  base.define_callbacks :recover
  base.skip_time_zone_conversion_for_attributes =[base.paranoid_column, :created_at, :updated_at]
end

モジュールがincludeされると自動的にparanoid_column(デフォルトはdeleted_at)とcreated_at,updated_atがTimeZoneを解除されています。論理削除の際にTimeZoneに起因するバグが発生するのを避けたのかも知れません。
と言うわけでこのgemが犯人と分かったので、paranoiaに置き換えて事なきを得ました。
分かってしまえば原因は単純でしたが、トラブルシュートの良い経験になりました。

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6