Skip to content

Instantly share code, notes, and snippets.

@pcreux
Last active June 14, 2017 18:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcreux/7c0f0d0a2754659de2fd to your computer and use it in GitHub Desktop.
Save pcreux/7c0f0d0a2754659de2fd to your computer and use it in GitHub Desktop.
railsmv - Rename rails services, models etc - railsmv app/services/create_user.rb app/services/user/create.rb
#!/usr/bin/env ruby
#
# Rename rails services, models etc as well as their test or spec files!
#
# Example: railsmv app/services/create_user.rb app/services/user/create.rb
#
require 'optparse'
dry_run = false
opts = OptionParser.new do |opts|
opts.banner = "Usage: railsmv [-n] FROM_PATH TO_PATH"
opts.on("-n", "--dry-run", "Outputs what would change without performing any changes") do
dry_run = true
end
opts.on("-h", "--help", "Show this message") do |v|
puts opts
exit 0
end
end
opts.parse!(ARGV)
if ARGV.size != 2
puts opts
exit -1
end
FROM = ARGV[0]
TO = ARGV[1]
# path should be app/{model,service,...}/*.rb
AppFile = Struct.new(:path) do
def class_name
base_path.gsub(/\.rb$/, '').
split('/').map { |underscored|
underscored.split('_').map{ |token|
token.capitalize
}.join('')
}.join('::')
end
def spec_path
path.gsub(/^app/, 'spec').gsub(/\.rb$/, '_spec.rb')
end
def test_path
path.gsub(/^app/, 'test').gsub(/\.rb$/, '_test.rb')
end
# path without app/{model,service,...}
def base_path
path.gsub(/^app\/\w+\//, '')
end
end
def system!(cmd)
puts cmd
system(cmd) or raise Error, "Failed to run #{cmd}"
end
Error = Class.new(StandardError)
Move = Struct.new(:from, :to, :options) do
def run!
if File.exists?(from)
unless File.directory?(File.dirname(to))
Dir.mkdir(File.dirname(to))
end
File.rename(from, to)
end
end
def validate!
raise Error, "#{from} does not exist!" if strict? && !File.exists?(from)
raise Error, "#{to} already exists!" if File.exists?(to)
self
end
def strict?
(options || {}).fetch(:strict, true)
end
def explain
"Move #{from} to #{to}"
end
end
Replace = Struct.new(:from, :to) do
def run!
system! cmd
end
def validate!
self
end
def explain
"Replace all occurences of #{from} to #{to} in #{directories.join(',')}"
end
private
def cmd
"find #{directories.join(' ')} | xargs perl -p -i -e 's/#{from}/#{to}/g'"
end
def directories
%w(app config lib features spec test)
end
end
GitCommit = Struct.new(:from, :to) do
def run!
system! "git rm #{from.path}"
system "git rm #{from.spec_path}" # can fail
system "git rm #{from.test_path}" # can fail
system! "git add #{to.path}"
system "git add #{to.spec_path}" # can fail
system "git add #{to.test_path}" # can fail
system! "git commit -am 'Rename #{from.class_name} to #{to.class_name}'"
end
def validate!
self
end
def explain
"Commit changes"
end
end
from = AppFile.new(FROM)
to = AppFile.new(TO)
commands = [
Move.new(from.path, to.path),
Move.new(from.spec_path, to.spec_path, strict: false),
Move.new(from.test_path, to.test_path, strict: false),
Replace.new(from.class_name, to.class_name),
# GitCommit.new(from, to)
]
commands.each(&:validate!)
if dry_run
commands.each { |command| puts command.explain }
exit 0
end
commands.each do |command|
puts command.explain
command.run!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment