2

inspired by some lisp magic of runtime edit sourcecode,

I want to do it in ruby. looks like I cannot get sourcecode from method/class, is there a way to do it?

I write a sample sourcecode here:

def helloworld n
  "hello #{n}"
end

o = Kernel.method :helloword

Kernel.define_singleton_method o.name do |n|
  eval o.source_code.sub('hello', 'hello world')
end

helloworld 'halida' #=> 'hello world halida'
1

3 Answers 3

1

You can easily get source code for a method in Ruby.

Imagine the following hypothetical class:

class Klass
  def self.foo
    :foo
  end

  def bar
    :bar
  end
end

As you can see, this class has two methods:

  • a class method .foo
  • an instance method #bar

Use .method and .instance_method to access them programmatically:

m1 = Klass.method :foo
=> #<Method: Klass.foo>

m2 = Klass.instance_method :bar
=> #<UnboundMethod: Klass#bar>

You can use the .source method to view their source code:

puts m1.source
  def self.foo
    :foo
  end
=> nil

puts m2.source
  def self.bar
    :bar
  end
=> nil

Because Ruby has open classes and dynamic loading, you can also add or change methods at run time. Just re-open the class and redefine the method:

Klass.foo
=> :foo

class Klass
  def self.foo
    :foobar
  end
end

Klass.foo
=> :footer

The other methods previously defined in the class will remain unaffected:

Klass.bar
=> :bar

WARNING: Redefining class behavior during runtime (also called "Monkey Patching") is a very powerful tool, it can also be somewhat dangerous. Current versions of Ruby support a much more controlled way of going about this called 'refinements'.

You can learn more about using refinements here

Sign up to request clarification or add additional context in comments.

Comments

0

You can't get the string representation of a part of the code, edit it and expect Ruby to reevaluate your changes. The only way to do something near to what you want is using ParseTree to get s-expressions of the source, edit and use Ruby2Ruby to generate a string of ruby code. Them add def ... and end to the string and call eval with it.

It's too hard and error-prone to be useful in a real-world situation. But I don't know any other way.

Note: ParseTree only works on Ruby 1.8.

2 Comments

You absolutely can get a string representation of the source code. Just use .method.source for class methods or .instance_method.source for instance methods. If you want to edit the string and reapply it you can just open the class redefine the method and use eval on the new string.
See also class_eval and instance_eval
0

Have a look at method_source gem. It's used by pry REPL for show-method command.

Looks like this gem utilizes standard Method#source_location (available in Ruby 1.9) to locate method and get its source code. Obviously, it doesn't work for dynamically defined methods and C methods. See docs for more information.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.