timestampsマクロとは何者なのか?

Ruby

みなさん、こんにちは。
今年は久しぶりに花粉の影響が強く苦しんでいる小林です。

また一つ、Ruby on Rails(以下、Rails)の謎が解けたので、紹介したいと思います。

今回のテーマは、こちらです。

  • timestampsマクロは何をしているのか?

timestampsマクロは何をしているのか?

timestampsマクロとは何か?

timestampsを呼び出すと作成日時(created_at)、更新日時(updated_at)を自動的に作成してくれます。

# db/migrate/2023032562631_create_products.rb
class CreateProducts < ActiveRecord::Migration[7.0]
  def change
    create_table :products do |t|
      t.string :name
      t.text :description

      t.timestamps
    end
  end
end
sample=# \d products
 id                  | bigint                                                | | not null | nextval('products_id_seq'::regclass)
 name            | character varying                           | |               | 
 description  | text                                                  | |               | 
 created_at  | timestamp(6) without time zone | | not null | 
 updated_at | timestamp(6) without time zone | | not null |

(↑うまく整形できなかったので、諦めました。)

Railsガイドにも記載されています。

timestampsマクロは、created_atupdated_atという2つのカラムを追加します。これらの特殊なカラムが存在する場合、Active Recordによって自動的に管理されます。

引用:Railsガイド#1 マイグレーションの概要

使用する分にはこれで十分なのですが、中で何をやっているのだろうと気になってしまったのが事の始まりでした。

何をしているのか?

結論から言うと、さほど複雑なことはしていませんでした。
active_record/connection_adapters/abstract/schema_definitions.rb#L460-L469

def timestamps(**options)
  options[:null] = false if options[:null].nil?

  if !options.key?(:precision) && @conn.supports_datetime_with_precision?
    options[:precision] = 6
  end

  column(:created_at, :datetime, **options)
  column(:updated_at, :datetime, **options)
end

要は、自身で以下のように書けるけど、timestampsマクロを使用すれば、記述量が減らせて楽ですよ。ということです。

# db/migrate/2023032562631_create_products.rb
class CreateProducts < ActiveRecord::Migration[7.0]
  def change
    create_table :products do |t|
      t.string :name
      t.text :description

      t.datetime :created_at, null: false, precision: 6
      t.datetime :updated_at, null: false, precision: 6
    end
  end
end

最後に

今回は、仕組みが複雑怪奇というよりも、どこで定義されているかが見つけられずにもやもやしていたので、読み込みが足りないなと痛感しました。

タイトルとURLをコピーしました