Skip to content

Instantly share code, notes, and snippets.

@rzane
Created May 18, 2017 20:03
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 rzane/6ac18ddaa646a4d2be618e6e06008a7b to your computer and use it in GitHub Desktop.
Save rzane/6ac18ddaa646a4d2be618e6e06008a7b to your computer and use it in GitHub Desktop.
Fix deprecated ActiveModel::Dirty methods for Active Record 5.1
class After < Struct.new(:text)
def call
text.gsub(Model::FIXES[0], 'saved_change_to_\1?')
.gsub(Model::FIXES[1], '\1_before_last_save')
end
end
class Before < Struct.new(:text)
def call
text.gsub(Model::FIXES[0], 'will_save_change_to_\1?')
.gsub(Model::FIXES[1]) { raise "Failed to convert: #{line}" }
end
end
class Model
attr_reader :file
FIXES = [
/(\w+)_changed\?/,
/(\w+)_was/
]
def initialize(file)
@file = file
end
def solve
fixed_lines = File.readlines(file).reduce([]) do |acc, line|
fixed = fix(line, acc) if needs_fix?(line)
if fixed && commit?(line, fixed)
acc + [fixed.call]
else
acc + [line]
end
end
File.open(file, 'w') { |f| f.write(fixed_lines.join) }
end
def needs_fix?(line)
FIXES.any? { |re| line.match? re }
end
def commit?(line, fixed)
puts "FILE: #{file}"
puts "CALLBACK: #{fixed.class.to_s.downcase}_*"
puts "CHANGE: #{line}"
puts "TO: #{fixed.call}"
loop do
print 'Replace? (y/n): '
answer = $stdin.gets.chomp
next unless answer.match?(/[yn]/i)
puts "\n"
break answer.match?(/y/i)
end
end
def fix(text, previous_lines)
find_solution(text, previous_lines)
end
def find_solution(text, previous_lines)
(previous_lines + [text]).reverse.each do |line|
case line
when /after_(create|update|save|destroy)/
return After.new(text)
when /before_(create|update|save|destroy)/
return Before.new(text)
when /def ([\w?]+)/
return find_def_solution(Regexp.last_match[1], text, previous_lines)
end
end
nil
end
def find_def_solution(meth, text, previous_lines)
previous_lines.each do |line|
case line
when /after_(create|update|save|destroy)\s*:#{meth}/
return After.new(text)
when /before_(create|update|save|destroy)\s*:#{meth}/
return Before.new(text)
end
end
nil
end
end
Dir.glob(ARGV.first || 'app/models/**/*.rb').each do |f|
Model.new(f).solve
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment