この記事は、Redmine Advent Calendar 2024 の9日目の内容になります。
はじめに
Redmineでは運用時のデフォルトデータの読み込みに load_default_data
タスク、開発時のテストデータの読み込みにはRailsの db:fixtures:load
タスクを利用することが多いと思います。
ただ、Redmineでテスト・デモ用に個別にカスタマイズしたデータを保存・復元できると、間違った操作を行ってしまった場合も簡単に元の状態に復元でき、YAML形式のフィクスチャファイルの編集・コード管理もできて便利なように思いましたので、少し調べてみました。
データベースの内容をフィクスチャ(fixture)に保存する
最初は以下のStack Overflow記事を参考に、モデルベースで進めようとしてましたが、
Active Recordの has_and_belongs_to_many
(多対多)関連付けとなっているテーブル(projects_trackers
など、rake db:migrate
後の db/schema.rb
内で id: false
のもの)の保存に対応できず、断念しました...。
どうしたものかと考えていたところ、Redmineの lib/tasks
フォルダ内に extract_fixtures.rake
という古いタスクがあり、データベース内のテーブルベースで上記の多対多関連付けテーブルも問題なさそうでしたので、こちらを新しいRailsでも動作するよう修正してみました。
1つ目のパッチがメインの修正で、ヘッダのライセンスコメントを除くコード部分は以下となります。
desc 'Create YAML test fixtures from data in an existing database.
Defaults to development database. Set RAILS_ENV to override.'
task :extract_fixtures => :environment do
dir = ENV['DIR'] || './tmp/fixtures'
FileUtils.mkdir_p(dir)
sql = "SELECT * FROM %s"
skip_tables = ["schema_migrations", "ar_internal_metadata"]
ActiveRecord::Base.establish_connection
(ActiveRecord::Base.connection.tables - skip_tables).each do |table_name|
i = "000"
File.open(File.join(dir, "#{table_name}.yml"), 'w') do |file|
data = ActiveRecord::Base.connection.select_all(sql % table_name)
file.write data.inject({}) { |hash, record|
# cast extracted values
ActiveRecord::Base.connection.columns(table_name).each { |col|
record[col.name] = ActiveRecord::Type.lookup(col.type).deserialize(record[col.name]) if record[col.name]
}
hash["#{table_name}_#{i.succ!}"] = record
hash
}.to_yaml
end
end
end
上記のコードをコピーして、Redmineの lib/tasks/extract_fixtures.rake
ファイルのコード部分に上書きすれば、以下のようにコマンドを実行することで、データベースの内容をフィクスチャに保存することができます。
bundle exec rake extract_fixtures DIR=(保存先ディレクトリ (デフォルト: ./tmp/fixtures))
保存したフィクスチャを読み込む
保存したフィクスチャを読み込むには以下を実行します。
bundle exec rake db:fixtures:load FIXTURES_PATH=(保存先ディレクトリ)
なお、フィクスチャの読み込み時には、データベース内のテーブル内容が削除されますので、間違って本番環境データを削除したりすることがないよう、十分注意してください。
参考リンク
- db:fixtures:loadをspec/fixtures以下のファイルを見るようにする - miyohide's blog
- Fixture はどのようにデータをロードしているか | hidakatsuya.dev
注意事項
- 上述のパッチですが、まだ提案段階なので、今後レビューなどで仕様が変わるかもしれません
- テスト・デモ用の軽めのデータ量を想定しています。大量のデータが含まれる場合は、YAML形式ではファイル容量が増大するので、CSV形式など、別のファイル形式に保存・復元するrakeタスク作成が必要かもしれません