0

I have a function that I would like to call and have it return the name of the function it was called from. Here is the function:

def get_pos func = __method__.to_s puts "You are in #{func}" end 

I understand that __method__ returns the name of the method it is currently being executed in.

I am trying to call get_pos() from test and this is the output I want to get:

def test get_pos end You are in test 

Instead I get the following

You are in get_pos 

I understand why this is happening. Since __method__ is located inside the getpos function it returns the name of that function.

I know that if i make the following change and pass __method__ as an argument to the function, I'll get the expected result. Which is:

def get_pos(method) puts "You are in #{method}" end def test get_pos(__method__.to_s) end You are in test 

The code has been simplified but is part of functionality in a logger where I want to be able to dump data about the current location in the code to a log and know exactly what module,class,function I am in.

Is there a better/cleaner way to do this than passing __method__ as a parameter to the function each time?

2
  • "[...] and this is the output I get" – don't you mean "this is the output I want"? Commented Jan 3, 2018 at 14:23
  • @Stefan: Correct, edited. Commented Jan 3, 2018 at 18:21

2 Answers 2

3

Why don't you use __callee__ from Kernel object?

I refactored your code:

def current puts __callee__ end def test_caller current end test_caller 

Which outputs current in this case.

There are all sorts of interesting methods in the Kernel Object. I recommend to take a look to the API here.

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

9 Comments

In this example, __callee__ and __method__ return the same value. The OP wants the method to return the name of the method it was called from, not its own name.
The only difference between __method__ and __callee__ is they work differently for aliases. Since this answer does not mention aliases at all, and even more, it adds zero value to what the OP had already, I doubt I understand how it could get upvoted 3 times and even be chosen as a correct answer. The answer by @Stefan is correct, btw.
I'll remove the answer if the answer got unaccepted, I misread.
Who knows? Maybe the OP wants something else :-)
I reread again, and he actually wants what his method is calling, using __method__ but in a cleaner way, he doesn't want the stack, he wants the current method without sending a parameter, which is achieved with __callee__, probably that's why he accepted my answer.
|
3

You can use caller_locations which returns an array of Thread::Backtrace::Location instances: (starting at index 1 by default, excluding the current method)

def foo caller_locations.map(&:base_label) end def bar foo end def baz bar end baz #=> ["bar", "baz", "<main>"] 

So foo was called from bar which was called from baz which was called in <main>.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.