Last active
June 14, 2017 18:27
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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