change_table の remove_timestamps が未対応オプションでエラーを発生させるように修正
Rails のマイグレーションで change_table ブロック内の remove_timestamps が if_exists や if_not_exists オプションを無視していた問題を解消し、同様のヘルパーと同等に未対応オプションで ArgumentError を即時通知するようになりました。
背景
change_table ヘルパー群は、t.remove, t.remove_index, t.timestamps などに対して 未対応オプション が渡された場合に raise_on_if_exist_options を呼び出し、ArgumentError を発生させて失敗を早期に顕在化させています。t.remove_timestamps だけがこのチェックを欠いていたため、呼び出し側はオプションが有効であるかのように錯覚し、マイグレーションの意図が不透明になるケースがありました。
この不整合はテストでも捕捉できず、実運用でのマイグレーション失敗が発覚するリスクを孕んでいました。PR #57988 は、remove_timestamps の挙動を他のヘルパーと揃えることを目的に作成されました。
技術的な変更
activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb の Table#remove_timestamps メソッド冒頭に raise_on_if_exist_options(options) の呼び出しが追加されました。これにより、if_exists: または if_not_exists: が渡された時点で ArgumentError がスローされます。
def remove_timestamps(**options)
raise_on_if_exist_options(options)
@base.remove_timestamps(name, **options)
end
同様のチェックは既に remove, remove_index, timestamps などで実装されており、今回の変更で メソッド間の一貫性 が確保されました。さらに、activerecord/test/cases/migration/change_table_test.rb に新しいテストケースが追加され、if_exists: オプションが渡された際に ArgumentError が確実に発生することを検証しています。
def test_remove_timestamps_with_if_exists_raises_error
assert_raises(ArgumentError) do
with_change_table do |t|
t.remove_timestamps if_exists: true
end
end
end
テスト追加により、将来的な回帰を防止すると同時に、開発者が期待通りの例外が発生することを確認できるようになりました。
設計判断
この変更は Fail‑Fast(早期失敗) の設計原則に沿った判断です。未サポートオプションを黙って無視する代わりに、明示的に例外を発生させることで、マイグレーション実行時に問題を即座に検出できます。
また、設定キーの追加 ではなく既存メソッドにチェックロジックを組み込む方針が採られました。これにより API の破壊的変更を回避し、既存コードベースへの影響を最小限に抑えつつ、一貫したエラーハンドリングを実現しています。
まとめ
remove_timestamps が if_exists/if_not_exists オプションを受け取った際に ArgumentError をスローするようになり、change_table ヘルパー全体で未対応オプションの取り扱いが統一されました。この修正はマイグレーションの安全性を高め、開発者が意図しないオプションの無視によるバグを防止します。