Skip to content

Instantly share code, notes, and snippets.

@h-lame
Created June 6, 2012 08:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save h-lame/2880696 to your computer and use it in GitHub Desktop.
Save h-lame/2880696 to your computer and use it in GitHub Desktop.
Model rename refactor script. (From @threedaymonk)
#!/usr/bin/env ruby
class Renamer
attr_reader :from, :to
def initialize(from, to)
@from = from
@to = to
end
def x_xes(s)
s.pluralize.underscore
end
def XXes(s)
s.pluralize
end
def x_x(s)
s.underscore
end
def XX(s)
s
end
def constant(s)
s.upcase
end
def rename_files(files)
files.each do |file|
source = File.read(file)
[:x_xes, :XXes, :x_x, :XX, :constant].each do |action|
source.gsub!(__send__(action, from), __send__(action, to))
end
File.open(file, "w"){ |f| f << source }
end
files.each do |a|
b = a.dup
[:x_xes, :x_x].each do |action|
b.gsub!(__send__(action, from), __send__(action, to))
end
next if a == b
FileUtils.mkdir_p(File.dirname(b))
FileUtils.mv(a, b)
end
end
def tables_with_fkeys(reference_class)
Dir["#{Rails.root}/app/models/*.rb"].inject({}){ |tables, path|
basename = File.basename(path, File.extname(path))
require basename
klass = basename.camelize.constantize
next tables unless klass.ancestors.include?(ActiveRecord::Base)
fields = klass.reflections.select{ |k,v| !v.options[:polymorphic] && v.macro == :belongs_to && v.klass == reference_class }.map{ |k,v| k }
polymorphic_fields = klass.reflections.select{ |k,v| v.options[:polymorphic] && v.macro == :belongs_to }.map{ |k,v| k }
if fields.any? || polymorphic_fields.any?
tables[klass.table_name] = [fields, polymorphic_fields]
end
tables
}
end
def write_migration
timestamp = Time.now.strftime("%Y%m%d%H%M%S")
tables = [{:from => x_xes(from), :to => x_xes(to)}]
columns = []
types = []
tables_with_fkeys(from.constantize).each do |table, (fields, polymorphic_fields)|
fields.each do |field|
columns << {:table => table, :from => "#{field}_id", :to => "#{field.to_s.sub(x_x(from), x_x(to))}_id"}
end
polymorphic_fields.each do |field|
types << {:table => table, :column => "#{field}_type", :from => XX(from), :to => XX(to)}
end
new_table_name = table.sub(x_xes(from), x_xes(to)).sub(x_x(from), x_x(to))
unless new_table_name == table
tables << {:from => table, :to => new_table_name}
end
end
open("#{Rails.root}/db/migrate/#{timestamp}_rename_#{x_x(from)}_to_#{x_x(to)}.rb", "w") do |f|
f.puts %{class Rename#{from}To#{to} < ActiveRecord::Migration}
f.puts %{ def self.up}
types.each do |t|
f.puts %{ execute "UPDATE #{t[:table]} SET #{t[:column]} = '#{t[:to]}' WHERE #{t[:column]} = '#{t[:from]}'"}
end
columns.each do |c|
f.puts %{ rename_column "#{c[:table]}", "#{c[:from]}", "#{c[:to]}"}
end
tables.each do |t|
f.puts %{ rename_table "#{t[:from]}", "#{t[:to]}"}
end
f.puts %{ end}
f.puts
f.puts %{ def self.down}
tables.reverse_each do |t|
f.puts %{ rename_table "#{t[:to]}", "#{t[:from]}"}
end
columns.reverse_each do |c|
f.puts %{ rename_column "#{c[:table]}", "#{c[:to]}", "#{c[:from]}"}
end
types.reverse_each do |t|
f.puts %{ execute "UPDATE #{t[:table]} SET #{t[:column]} = '#{t[:from]}' WHERE #{t[:column]} = '#{t[:to]}'"}
end
f.puts %{ end}
f.puts %{end}
end
end
end
from, to, = ARGV
unless from && to
$stderr.puts "Usage: #$0 OldModelName NewModelName"
exit
end
require File.dirname(__FILE__) + '/../config/environment'
files = Dir["{app,views,test,features,config,lib,public}/**/*.{erb,rb,feature,less,css,rjs,rxml}", "db/seeds.rb"]
r = Renamer.new(from, to)
r.write_migration
r.rename_files(files)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment