Alex Young
9/9/2006 5:44:00 PM
James Edward Gray II wrote:
> On Sep 9, 2006, at 10:33 AM, Alex Young wrote:
>
>> James Edward Gray II wrote:
>>> On Sep 9, 2006, at 9:41 AM, Alex Young wrote:
>>>> Ok, so it's a real bodge to try to rename a method before runtime.
>>>> What happens if we annotate the method to be renamed the next time
>>>> it's run? We could run the script in question under an environment
>>>> not totally unlike xmp. The first thing it would do is alter the
>>>> source file according to the annotation. It would then add an
>>>> appropriate method_missing to Object to do a rename in the original
>>>> source file whenever the method was called, and then load() the file.
>>> And what happens if the execution never calls the given method, for
>>> whatever reason, or only reaches some of the places it is used?
>> That's why you run your test suite through it. You do have 100% line
>> coverage, right? :-)
>
> Well it's a clever idea. Show us the prototype. ;)
Well, you asked for it :-) The usual provisos for prototype code apply:
$ cat rename_method.rb
$obj_replacement_table = {}
class Object
def method_missing(sym, *args, &block)
if $obj_replacement_table.has_key? sym.to_s
filename, line_num = caller[0].split(':')[0,2]
l = line_num.to_i - 1
line_arr = File.readlines(filename)
line_arr[l] = line_arr[l].sub(sym.to_s,
$obj_replacement_table[sym.to_s])
File.open(filename, 'wb'){|f| f.write line_arr}
self.send($obj_replacement_table[sym.to_s].to_sym, *args, &block)
end
end
end
def process_file(filename)
line_arr = File.readlines(filename)
line_arr.each_with_index do |line,i|
if line.chomp =~ /(\s+)def (\w+)(.*)#\s*becomes\s+(\w+)/
line_arr[i] = "#{$1}def #{$4}#{$3}# was #{$2}\n"
$obj_replacement_table[$2] = $4
end
end
File.open(filename, 'wb'){|f| f.write line_arr }
end
process_file(ARGV[0])
load(ARGV[0])
$ cat subject.rb
class TestClass
def my_method(foo) # becomes my_new_method
puts foo
end
end
def meth_calling_renamed(t)
t.my_method('Ok2')
end
t = TestClass.new
t.my_method('Ok1')
meth_calling_renamed(t)
$ ruby rename_method.rb subject.rb
Ok1
Ok2
$ cat subject.rb
class TestClass
def my_new_method(foo) # was my_method
puts foo
end
end
def meth_calling_renamed(t)
t.my_new_method('Ok2')
end
t = TestClass.new
t.my_new_method('Ok1')
meth_calling_renamed(t)
There's a *lot* of scope for improvement in there, obviously, but that's
the general idea.
--
Alex