How to Find Where a Method Is Defined At Runtime

How to find where a method is defined at runtime?

This is really late, but here's how you can find where a method is defined:

http://gist.github.com/76951

# How to find out where a method comes from.
# Learned this from Dave Thomas while teaching Advanced Ruby Studio
# Makes the case for separating method definitions into
# modules, especially when enhancing built-in classes.
module Perpetrator
def crime
end
end

class Fixnum
include Perpetrator
end

p 2.method(:crime) # The "2" here is an instance of Fixnum.
#<Method: Fixnum(Perpetrator)#crime>

If you're on Ruby 1.9+, you can use source_location

require 'csv'

p CSV.new('string').method(:flock)
# => #<Method: CSV#flock>

CSV.new('string').method(:flock).source_location
# => ["/path/to/ruby/1.9.2-p290/lib/ruby/1.9.1/forwardable.rb", 180]

Note that this won't work on everything, like native compiled code. The Method class has some neat functions, too, like Method#owner which returns the file where the method is defined.

EDIT: Also see the __file__ and __line__ and notes for REE in the other answer, they're handy too. -- wg

Get the name of method at runtime

I assume this is Java... If that is the case, this returns the name of the method you are currently in.

String methodName = new Exception().getStackTrace()[0].getMethodName()

Be careful though, don't put this in a method, because then that will return the name of that method. You could also use this:

public String getMethodName() {
return new Exception().getStackTrace()[1].getMethodName();
}

This observes the second element of the stack trace, returning the correct method name.

UPDATE:

Though the first does what it takes, this is nicer: doesn't involve creating a new object at least:

Thread.currentThread.getStackTrace()[1].getMethodName();

Warning I have to mention that all this however has an adverse impact on performance...

Finding out where methods are defined in Ruby/Rails (as opposed to Java)

The Pry gem is designed precisely for this kind of explorative use-case.

Pry is an interactive shell that lets you navigate your way around a program's source-code using shell-like commands such as cd and ls.

You can pull the documentation for any method you encounter and even view the source code, including the native C code in some cases (with the pry-doc plugin). You can even jump directly to the file/line where a particular method is defined with the edit-method command. The show-method and show-doc commands also display the precise location of the method they're acting on.

Watch the railscast screencast for more information.

Here are some examples below:

pry(main)> show-doc OpenStruct#initialize

From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 11

visibility: private
signature: initialize(hash=?)

Create a new OpenStruct object. The optional hash, if given, will
generate attributes and values. For example.

require 'ostruct'
hash = { "country" => "Australia", :population => 20_000_000 }
data = OpenStruct.new(hash)

p data # -> <OpenStruct country="Australia" population=20000000>

By default, the resulting OpenStruct object will have no attributes.

pry(main)>

You can also look up sourcecode with the show-method command:

pry(main)> show-method OpenStruct#initialize

From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 9

def initialize(hash=nil)
@table = {}
if hash
for k,v in hash
@table[k.to_sym] = v
new_ostruct_member(k)
end
end
end
pry(main)>

See http://pry.github.com for more information :)

How do I find where a Ruby method is called at runtime?

The suggestion to use caller() is fine for figuring out the stack trace from a certain method. However, I'll also share (what I think is) the solution to your problem.

The to_s method returns a string that is used to set an instance variable dynamically. The DetailsViewBuilder's object_id is part of the variable name. The object ID represents the object's location in memory. Contrary to intuition, the object_id of an object may sometimes be negative integer. Whether or not this happens may also be platform-dependant. This explains why you are only seeing this error in production. The negative object ID causes the instance variable name to become something like @content_for_details_view_builder__-626960428, which contains a dash. Dashes are not allowed as part of identifiers in Ruby. Hence the error.

It seems that you are using an instance of DetailsViewBuilder as argument to content_for somewhere, is that right? Or it might happen indirectly, in some library you are using.

In any case, if this is the correct behaviour, and all you want is to avoid the instance variable name error, then the fix is simple. Change object_id to object_id.abs to guarantee that the instance variable never contains a dash:

def to_s
"#{self.class.name.underscore}__#{object_id.abs}"
end

Ruby / Rails -- from where was a method was included?

Whatever context you're in you can get the source location by using:

obj.method(:method).source_location

It won't give you exactly what you want, but the Rails core developers are good about properly namespacing things. The following example can be run from the rails console:

Time.method(:zone).source_location

["/Users/pete/.rvm/gems/ruby-1.9.2-p290@gemset/gems/activesupport-3.2.3/lib/active_support/core_ext/time/zones.rb", 9]

Then you can go to the Rails source and search for that file. Hint: type 't' on Github and start typing. It will bring you to that file and you can see that it is defined directly on the Time class.

How to check if C++ abstract method is defined at runtime

As you can't instantiate an abstract class, any class you encounter at runtime will not have any pure virtual methods (unless you're in a constructor or destructor at the time), they'll all have been overriden with a non-pure overrider. There is nothing to check.



Related Topics



Leave a reply



Submit