[LRUG] Can't hide instance method if defined in native extension?

Peter Vrabel kybu at kybu.org
Sun Nov 20 02:51:20 PST 2011


On Mon, 14 Nov 2011 14:23:13 -0000, Sean O'Halpin <sean.ohalpin at gmail.com>  
wrote:

> On Sun, Nov 13, 2011 at 10:25 PM, Peter Vrabel <kybu at kybu.org> wrote:
>> Hi guys,
>>
>> I recently came across a strange behavior. I would like to measure time
>> spent executing Mysql statement, so I tried to hide 'execute' instance
>> method of Mysql::Stmt and my first idea was to use my custom module  
>> that I
>> include into Mysql::Stmt class. But then I found that I can't do that,
>> original 'execute' method is always called. Here is a small edited  
>> snippet:
>>
>
> [snip example]
>
> Hi,
>
> As others have pointed out, including a module inserts methods above
> the current class in the inheritance hierarchy so you can't use it to
> override methods defined in that class. You can however use extend on
> an instance to override methods defined in the class.
>
> I generally use one of the following two methods. The first is a
> 'hygenic' version of alias_method in that you can use the same
> technique in multiple included modules without worrying about whether
> the method has been already aliased. It's clean but it's slow (the
> bind is costly). The second (which I use more often) is to use extend
> with super. You can even combine both methods together.
>
> # 'hygenic' way to override method via include
>
> class Foo
>   def foo(*args, &block)
>     p [Foo, :foo, args, block]
>   end
> end
>
> Foo.new.foo(1, 2, 3)
>
> module Override
>   def self.included(other)
>     original_foo = other.instance_method(:foo)
>     other.class_eval {
>       define_method :foo do |*args, &block|
>         p Override
>         args = args.reverse
>         original_foo.bind(self).call(*args, &block)
>       end
>     }
>   end
> end
>
> class Foo
>   include Override
> end
>
> Foo.new.foo(1, 2, 3)
>

Thanks, I didn't know about that first method.

kybu



More information about the Chat mailing list