- Rails デフォルトの db:* 系タスクを誤って production 環境で実行すると悲惨なので Rakefile は使いたくない
- しかしバッチ処理などは Rake タスクとしてまとめておきたい(console で都度実行するのはオペミスが怖い)
という事情があって、個別にスクリプトを追加してもいいんだけど(実際いままではそうしてきた)、 Rake でやりたかったのでやってみた。環境は Rails 2.x.y と Rake 0.8.7 です。
https://gist.github.com/1058373
# Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require(File.join(File.dirname(__FILE__), 'config', 'boot')) require 'rake' require 'rake/testtask' require 'rake/rdoctask' $:.each do |load_path| rails_task_loader_file = 'tasks/rails.rb' rails_task_loader_path = File.expand_path(File.join(load_path, rails_task_loader_file)) if File.exist?(rails_task_loader_path) rails_task_dir_path = File.dirname(rails_task_loader_path) rails_task_environment = File.join(rails_task_dir_path, 'misc.rake') load rails_task_environment end end # Load any custom rakefile extensions Dir["#{RAILS_ROOT}/lib/tasks/**/*.rake"].sort.each { |ext| load ext }
$ rake -f Rakefile2 -T
とかすると RAILS_ROOT/lib/tasks 以下にある *.rake で定義されたタスクのみが列挙される。
オリジナルの Rakefile は
require 'tasks/rails'
で rails-x.y.z/lib/tasks/rails.rb を読み込んでいて、そいつのなかで同じディレクトリ内の *.rake を load している。この load は rake-x.y.z/lib/rake.rb のなかで def load ... end と定義されているやつっぽい(実体は Kernel#load の呼び出し)
この *.rake たちが Rails のデフォルトの Rake タスクで、中身をみてみると db:* とか test:* とか見慣れたタスクが定義してある。このうち misc.rake に :environment というタスクが定義されていて、これを読み込まないと
task :foo => :environment do # ... end
のように定義されたタスクが実行できない。ので、自前で作った Rakefile2 で $: の中から 'tasks/rails.rb' があるパスを探してそこにある misc.rake だけを load してやり、その後自前の Rake タスクをロードしてやると、 RAILS_ROOT/lib/tasks/*.rake だけを安全に実行する Rakefile をつくることができる。
ファイル名(拡張子)決め打ちだったりとかいろいろ力業でアレな感じだけど、オペミスで事故るリスクを考えたらマシかなと。