tags:

views:

51

answers:

4

I want to (efficiently) get the symbol an aliased method is called with at runtime. A direct efficient access to a stack frame object of some sort to get it would be the fantasy.

ie:

class Foo
  def generic_call(*args)
    puts("generic_call() was called by using #{???}")
  end

  alias :specific_call1 :generic_call
  alias :specific_call2 :generic_call

end

Foo.new.specific_call1
Foo.new.specific_call2

the result I'd want


generic_call() was called by using specific_call1()
generic_call() was called by using specific_call2()

+1  A: 
class Foo
  def generic_call()
    puts "generic call was called by #{caller[0][/in `([^']+)'/, 1]}"
  end

  def specific_call1() generic_call end
  def specific_call2() generic_call end
end

Foo.new.specific_call2 # Prints: generic call was called by specific_call2

This will however not work if you use alias to create specific_callN from generic_call because methods created by alias are actually a copy of the original method - they don't actually call the original method (which is why you can freely redefine the original without affecting the alias).

sepp2k
yep alias assigns the "function pointer" ie: lambda to another symbol in the object's hash leaving the original symbol free to be manipulated. Now It is possible the actual "code" block assigned to the symbol is anoymous and the "name comes from the symbol it is assigned to, but :)
Peter Kennard
A: 

There's no built-in way to do this. You can kind of hack it like:

def current_method_name
  caller[0].split('`').last.split('\'')[0]
end
Chuck
yes 'know about that :)not efficient :)
Peter Kennard
+1  A: 

A code snippet to get the current method name:

module Kernel
    private
    # Defined in ruby 1.9
    unless defined?(__method__)
      def __method__
        caller[0] =~ /`([^']*)'/ and $1
      end
    end
  end
khelll
defeats the purpose which is to have a method that can do something with the symbol without having to duplicate and instantiate a new code block for each one :)
Peter Kennard
pardon I want to delete the prior comment - it is wrong :)
Peter Kennard
A: 

Maybe, you want something like this?

class Object
  def named_alias(name, generic_name)
    ([Class, Module].include?(self.class) ? self : self.class).class_eval do
      define_method(name) { |*args| send(generic_name, name, *args) }
    end
  end
end

class Foo
  def generic_call(f, *args)
    puts("generic_call() was called by using #{f} with #{args}")
  end

  # def specific_call1(*args)
  #     generic_call(:specific_call1, *args)
  # end
  named_alias(:specific_call1, :generic_call)
  named_alias(:specific_call2, :generic_call)
end

Foo.new.specific_call1
Foo.new.specific_call2

Disclaimer: I don't know Ruby, I've just Googled how one performs currying there, then adapted the code a bit.

drdaeman