What the Purpose of Bind/Unbind Methods in Ruby

What the purpose of bind/unbind methods in Ruby?

It is indeed useful for metaprogramming. Suppose you want to know the location of the source code for SomeClass#method. If you can generate an instance of SomeClass, then you can create a (bound) method instance of it on that SomeClass instance, on which you can call various methods to investigate some meta-data of the method. But what if you did not know the method signature of SomeClass#new, or what if SomeClass's constructor method was named other than SomeClass#new? Just safely creating an instance of SomeClass can be difficult. That is where unbound method comes in handy. Without bothering with a particular instance of the class, or with how to create an instance, you can simply do SomeClass.instance_method(:a_method) (which is an unbound method), then call source_location on it to investigate the location of the definition:

unbound = SomeClass.instance_method(:a_method)
puts unbound.source_location

And when would this kind of metaprogramming be necessary in the real world applications? One example is when you are creating an IDE with functions for method lookup.

how to check what object that a method bind to?

The receiver of the method is returned by the aptly named Method#receiver method.

What mechanism is used to allow one to call methods defined in ruby root scope from that scope?

This is really special cased in Ruby. If you define methods in the global scope they get actually defined on Kernel which is included in every object by default.

Kernel is also there when no other context is defined. Since Class inherits also from Kernel methods defined on it are also in scope in class scopes.

Using instance_exec and converting a method to a Proc

It seems that, in Ruby, methods defined using def some_method are bound permanently to the class they're defined in.

So, when you call .to_proc on them they keep the binding of their original implementation, and you cannot rebind them. Well, you can, but only to an object of the same type as the first one. It's possible I could do some fancyness with inheritance, but I don't think so.

The solution becomes instead of using methods, I just put actual Procs into variables and use them then, as they're not bound until execution time.

Singleton method error from bind when called with the same metaclass

This should work for you:

class Module
def add_logging(*method_names)
method_names.each do |method_name|
original_method = method(method_name).unbind
define_singleton_method(method_name) do |*args, &blk|
puts "#{self}.#{method_name} called"
original_method.bind(self).call(*args, &blk)
end
end
end
end

# class method example
module MyModule
def self.module_method1
puts "hello"
end

add_logging :module_method1
end

MyModule.module_method1

# output:
#
# MyModule.module_method1 called
# hello


Related Topics



Leave a reply



Submit