Rails のモデル名・ファイル名・ディレクトリ名を一斉に変更するスクリプトを書いた(修正版)

Rails のモデル名変更スクリプトを、まだ名前を明かせぬ人と一緒にペアプロして作った。
全テスト、オールグリーンなので、多分大丈夫。まぁでも Git などの SCM は必須だねぇ。当然、無保証です。
あ、テーブル名・カラム名変更は誰か追加して完全版作ればいい。ウチは今 MongoDB なんで必要ないんすよー。


実行はこんな感じ。

$ rails runner ./script/rename Old New


肝心の内容は以下。
あー、変数名は before/after じゃなくて old/new の方が良かったなー。適当に直すがよろし。

script/rename:

#!/usr/bin/env ruby
# coding: utf-8

old = ARGV[0]
new = ARGV[1]

if old.blank? || new.blank?
  STDERR.puts "Usage: rails runner ./script/rename old new"
  exit 1
end

old = old.downcase
new = new.downcase
olds = old.pluralize
news = new.pluralize

def file_each(&block)
  Dir.glob('./**/*') do |file|
    next if file["script/"]
    next if file["Gemfile"] || file["Rakefile"] || file["Guardfile"] || file["config.ru"]
    next if file["vendor/"]
    next if file["config/"] && !file["routes.rb"]
    next if file["db/"]
    next if file["tmp/"] || file["log/"] || file["doc/"]
    next if file[".git/"]

    print "."  
    yield file 
  end
  puts
end

# ディレクトリ名を変更する
puts "ディレクトリ名を変更しています"
file_each do |file|
  next unless File.directory?(file)
  if file[olds]
    # 複数形を変更する
    File.rename(file, file.gsub(olds, news))
  elsif file[old]
    # 単数形を変更する
    File.rename(file, file.gsub(old, new))
  end
end

# ファイル名を変更する
puts "ファイル名を変更しています"
file_each do |file|
  next unless File.file?(file)
  if file[olds]
    # 複数形を変更する
    File.rename(file, file.gsub(olds, news))
  elsif file[old]
    # 単数形を変更する
    File.rename(file, file.gsub(old, new))
  end
end

# ファイルの中の文字列を変更する
puts "ファイルを変更しています"
file_each do |file|
  next unless (File.file?(file) && !File.extname(file).match(/\.(jpg|png|gif|ico)$/))
  # 複数形を変更する
  system %Q|sed -i s/#{olds}/#{news}/g #{file}|
  system %Q|sed -i s/#{olds.capitalize}/#{news.capitalize}/g #{file}|
  # 単数形を変更する
  system %Q|sed -i s/#{old}/#{new}/g #{file}|
  system %Q|sed -i s/#{old.capitalize}/#{new.capitalize}/g #{file}|
end

(11/29 修正:sed によるファイルの書き換えが sync する前に、ファイル名・ディレクトリ名の変更が走って中身が古いままだったので、sed の処理を後ろにまわした)
guard-spork なんか使ってる人は、再起動すれば、テスト通る。