SQLite仮想テーブルが`ignore_tables`に従うよう修正
SQLiteの仮想テーブルが ActiveRecord::SchemaDumper.ignore_tables の設定を無視してスキーマダンプに出力されていたバグが修正されました。1行の修正により、通常テーブルと同様に仮想テーブルもフィルタリングされるようになります。
背景
#56976 で報告されたこのバグは、SQLiteの仮想テーブルがスキーマダンプ時に ignore_tables の指定を無視するというものでした。ActiveRecord::SchemaDumper.ignore_tables に仮想テーブル名を追加しても、schema.rb には create_virtual_table "fts_docs", "fts5", ["content"] のように出力され続けていました。
この問題は、FTS5(全文検索)や Spatialite(#56969 参照)のような拡張機能が自動生成する仮想テーブルを schema.rb から除外したいケースで特に問題となっていました。これらの仮想テーブルは通常アプリケーションコード側で管理されるため、スキーマダンプへの混入を避けることが求められます。
技術的な変更
sqlite3/schema_dumper.rb の virtual_tables メソッドに、ignored? チェックが追加されました。変更箇所はわずか1行です。
変更前:
def virtual_tables(stream)
virtual_tables = @connection.virtual_tables
if virtual_tables.any?
# ...
end
end
変更後:
def virtual_tables(stream)
virtual_tables = @connection.virtual_tables.reject { |name, _| ignored?(name) }
if virtual_tables.any?
# ...
end
end
@connection.virtual_tables が返すのは [name, type, columns] の形式のデータです。reject ブロックでは name のみを取り出し、親クラス ConnectionAdapters::SchemaDumper が持つ既存の ignored? メソッドに渡してフィルタリングしています。通常テーブルのダンプでも同じ ignored? メソッドが使われており、一貫した動作になります。
テストは virtual_table_test.rb に追加され、ignore_tables に "searchables" を指定した状態でスキーマダンプを実行し、create_virtual_table "searchables" が出力に含まれないことを検証します。
def test_schema_dump_ignores_virtual_tables_in_ignore_tables
output = dump_all_table_schema(["searchables"])
assert_not_includes output, 'create_virtual_table "searchables"'
end
設計判断
通常テーブルとの対称性を保つ最小限の修正 が採用されました。
ignored? メソッドは親クラスである ConnectionAdapters::SchemaDumper に既に定義されており、通常テーブルのフィルタリングで使われている共通ロジックです。仮想テーブルの処理だけがこのメソッドを呼んでいなかったという実装漏れを、reject の追加だけで修正しています。新たなメソッドや設定項目を導入せず、既存のインターフェースを活用することで、APIの複雑さを増やさずに一貫性を回復した判断といえます。
まとめ
virtual_tables メソッドへの1行追加により、SQLite仮想テーブルが ignore_tables の設定に従うようになりました。FTS5テーブルや Spatialite が生成する仮想テーブルを schema.rb から除外したいユースケースで、追加の回避策なしに期待通りの動作が得られます。