意外と知らないTimestamp

# ActiveRecordのTimestampについて

## config.rbの設定
`config.active_record.record_timestamps = false`
activerecordのtimestampをon/offする設定できる。

`config.active_record.default_timezone = :local`
デフォルトはUTCであるが、ローカルのタイムゾーンを設定できる。

`config.active_record.time_zone_aware_attributes = false`
ActiveRecordの全てのdatetime、timeカラムをタイムゾーンに対応させる。
デフォルトではUTCとしてDBに保存を行い、取得するときはTime.zoneを変換する。

`ActiveRecord::Base.time_zone_aware_types = [:datetime] or [:time]`
datetime、timeのみを設定することも可能

`ActiveRecord::Base.record_timestamps = false`
timestampの自動更新を一括offにできる

# Railsのソースコードを読んでみた
active_recordのtimestampについて調べてみました。主にここをみてます。
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/timestamp.rb

## create時

```ruby
    def _create_record
      if record_timestamps
        current_time = current_time_from_proper_timezone

        all_timestamp_attributes_in_model.each do |column|
          if !attribute_present?(column)
            _write_attribute(column, current_time)
          end
        end
      end

      super
    end
```
`all_timestamp_attributes_in_model`をeachで回して、該当するカラムを`_write_attribute`メソッドで現在日時に更新している。

`all_timestamp_attributes_in_model`は`timestamp_attributes_for_create_in_model`と`timestamp_attributes_for_update`を足したものなので、`created_at、created_on、updated_at、updated_on`のどれかがテーブルにあれば更新する。

```ruby
        def all_timestamp_attributes_in_model
          timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
        end
```
ちなみに、atだとdatetime、onだとdateのイメージです。

## updateの時
```ruby
    def _update_record(*args, touch: true, **options)
      if touch && should_record_timestamps?
        current_time = current_time_from_proper_timezone

        timestamp_attributes_for_update_in_model.each do |column|
          next if will_save_change_to_attribute?(column)
          _write_attribute(column, current_time)
        end
      end
      super(*args)
    end
```
update時はcreateの時と異なり`timestamp_attributes_for_create_in_model`のみをeachで回して、現在日時に更新してます。
`timestamp_attributes_for_create_in_model`は`updated_at`または`updated_on`が該当するものを抽出しています。

## 他のメソッドについてもみてみた
* max_updated_column_timestampメソッド
 
cache_keyを作るために使用している模様

```ruby
    def cache_key(*timestamp_names)
      if new_record?
        "#{model_name.cache_key}/new"
      else
        if cache_version && timestamp_names.none?
          "#{model_name.cache_key}/#{id}"
        else
          timestamp = if timestamp_names.any?
            ActiveSupport::Deprecation.warn(<<-MSG.squish)
              Specifying a timestamp name for #cache_key has been deprecated in favor of
              the explicit #cache_version method that can be overwritten.
            MSG

            max_updated_column_timestamp(timestamp_names)
          else
            max_updated_column_timestamp
          end

          if timestamp
            timestamp = timestamp.utc.to_s(cache_timestamp_format)
            "#{model_name.cache_key}/#{id}-#{timestamp}"
          else
            "#{model_name.cache_key}/#{id}"
          end
        end
      end
    end
```
https://github.com/rails/rails/blob/1c9b6ab466eff59a8a59bc2e38720fe1983c2c33/activerecord/lib/active_record/integration.rb#L54

* clear_timestamp_attributesメソッド

initialize_dupで使用(initialize_dupはdupした時に呼ばれる)

# 所感
`created_on`、`updated_on`を使うと便利になるケースが思い浮かびませんでした。何かこういうPJTで使ったよーみたいなのがあると、是非教えてください。